آموزش Entity Framework (بخش دوم)
بسم الله الرحمن الرحیم
آموزش Entity Framework
بهینه سازی Entity Framework
قبل از مطالعه این دوره آموزشی بهتر است دوره های زیر را نیز مطالعه کنید.
آموزش Code first
آموزش migration و Entity Framework در Code First
بخش اول
Entity Framework & ChangeTracker
در بخش قبل با مفاهیم ابتدایی آشنا شدیم در این بخش قصد داریم مثال قبل را کامل نماییم و همچنین با خاصیت جدیدی با نام ChangeTracker آشنا شویم.
با استفاده از خاصیت ChangeTracker شما می توانید اطلاعات کاملی در خصوص Entity ها و عملیات های آنها و همچنین وضعیت ثبت شده برای آنها را بدست آورید.
برای تکمیل پروژه خود Model های زیر را به پروژه خود اضافه می کنیم.
public class Author : IPerson { public int AuthorId { get; set; } public string Name { get; set; } public string Biography { get; set; } } public class Reader : IPerson { public int ReaderId { get; set; } public string Name { get; set; } public string Username { get; set; } } public interface IPerson { string Name { get; } }
حال دستورات زیر را به Controller اضافه می کنیم
بسم الله الرحمن الرحیم
آموزش Entity Framework
بهینه سازی Entity Framework
قبل از مطالعه این دوره آموزشی بهتر است دوره های زیر را نیز مطالعه کنید.
آموزش Code first
آموزش migration و Entity Framework در Code First
بخش اول
Entity Framework & ChangeTracker
در بخش قبل با مفاهیم ابتدایی آشنا شدیم در این بخش قصد داریم مثال قبل را کامل نماییم و همچنین با خاصیت جدیدی با نام ChangeTracker آشنا شویم.
با استفاده از خاصیت ChangeTracker شما می توانید اطلاعات کاملی در خصوص Entity ها و عملیات های آنها و همچنین وضعیت ثبت شده برای آنها را بدست آورید.
برای تکمیل پروژه خود Model های زیر را به پروژه خود اضافه می کنیم.
public class Author : IPerson
{
public int AuthorId { get; set; }
public string Name { get; set; }
public string Biography { get; set; }
}
public class Reader : IPerson
{
public int ReaderId { get; set; }
public string Name { get; set; }
public string Username { get; set; }
}
public interface IPerson
{
string Name { get; }
}
حال دستورات زیر را به Controller اضافه می کنیم
#region Example Entity Framework and Change Tracker
// Load some entities into the context
context.Ablies.Load();
context.Authors.Load();
context.Readers.Load();
// Make some changes
context.Ablies.Find(1).PostName = "Code First";
context.Ablies.Remove(context.Ablies.Find(2));
context.Authors.Add(new Author { Name = "Esmaeil Sheidaei" });
context.Readers.Find(1).Username = "Ably.ir";
// Look at the state of all entities in the context
Response.Write("All tracked entities: < br/>");
foreach (var entry in context.ChangeTracker.Entries())
{
Response.Write(String.Format(
"Found entity of type {0} with state {1} < br/>",
ObjectContext.GetObjectType(entry.Entity.GetType()).Name,
entry.State));
}
// Find modified entities of any type
Response.Write("\nAll modified entities: < br/>");
foreach (var entry in context.ChangeTracker.Entries()
.Where(e => e.State == EntityState.Modified))
{
Response.Write(String.Format(
"Found entity of type {0} with state {1} < br/>",
ObjectContext.GetObjectType(entry.Entity.GetType()).Name,
entry.State));
}
// Get some information about just the tracked Ablies
Response.Write("\nTracked Ably: ");
foreach (var entry in context.ChangeTracker.Entries<Ably>())
{
Response.Write(String.Format(
"Found Ably {0}: {1} with original Name {2} < br/>",
entry.Entity.Id,
entry.Entity.PostName,
entry.Property(p => p.PostName).OriginalValue));
}
// Find all people (author or reader)
Response.Write("\nPeople: ");
foreach (var entry in context.ChangeTracker.Entries<IPerson>())
{
Response.Write(String.Format("Found Person {0}", entry.Entity.Name));
}
#endregion
نتیجه اجرای این دستورات به صورت زیر خواهد بود
All tracked entities:
Found entity of type Ably with state Modified
Found entity of type Ably with state Deleted
Found entity of type Ably with state Unchanged
Found entity of type Author with state Unchanged
Found entity of type Author with state Added
Found entity of type Reader with state Modified
All modified entities:
Found entity of type Ably with state Modified
Found entity of type Reader with state Modified
Tracked Ablies:
Found Ably 1: The New ADO.NET with original Name ADO.NET Blog
Found Ably 2: The Visual Studio with original Name The Visual Studio Blog
Found Ably 3: .NET Framework with original Name .NET Framework Blog
People:
Found Person ESH
Found Person Esmaeil
Found Person Esmaeil Sheidaei
همانطور که مشاهده می کنید ما به سادگی تمامی شی های مربوط به هر Model و یا تمامی Model ها را واکشی کرده ایم.
دستورات را بخش به بخش بررسی می کنیم تا ابهام این دستورات برطرف شود.
همانطور که مشخص است تمامی اطلاعات این سه Model از پایگاه داده واکشی شده است.
// Load some entities into the context
context.Ablies.Load();
context.Authors.Load();
context.Readers.Load();
در دستورات زیر برخی از این اطلاعات را تغییر داده ایم تا در کدهای بعدی بتوانیم آنها را بررسی کنیم، مثلا یک شی را از Model مربوط به Ably حذف کرده ایم و همچنین یک شی را به Model مربوط به Author اضافه کرده ایم و دو شی دیگر را تنها Find کرده ایم.
context.Ablies.Find(1).PostName = "Code First";
context.Ablies.Remove(context.Ablies.Find(2));
context.Authors.Add(new Author { Name = "Esmaeil Sheidaei" });
context.Readers.Find(1).Username = "Ably.ir";
با استفاده از دستور بالا ما می توانیم به تمامی Entity ها موجود که به یک Context معرفی شده اند، دسترسی داشته باشیم. این دستور می تواند بر اساس نوع Model ایی که به آن می دهیم اشیا مورد نظر را برگرداند.
context.ChangeTracker.Entries())
طبیعتا همه می دانید که Context نیز یک شی از DbContext می باشد که Model های ما به صورت زیر به آن معرفی شده اند.
public DbSet<Ably> Ablies { get; set; }
public DbSet<Author> Authors { get; set; }
public DbSet<Reader> Readers { get; set; }
با استفاده از بخش کد زیر ما تمامی Entity ها را واکشی می کنیم و همچنین نوع آنها را (Model) به همراه وضعیت فعلی آنها چاپ می کنیم.
در این جا ما هیچ کار پیچیده ای انجام نداده ایم، بلکه تنها با استفاده از Entity Framework و خاصیت ChangeTracker تمامی اشیایی که در Context ما که در کد قبل Load شده بودند را چاپ کردیم. با استفاده از کلاس ObjectContext و متد GetObjectType آن ما نوع شی جاری را به صورت entry.Entity.GetType به این تابع داده ایم و Name آن را برای نمایش چاپ کرده ایم، در آخر نیز از خاصیت State برای نمایش وضعیت این شی استفاده کرده ایم. بهتر است به بالا باز گردید و خروجی این بخش را مشاهده کنید.
// Look at the state of all entities in the context
Response.Write("All tracked entities: < br/>");
foreach (var entry in context.ChangeTracker.Entries())
{
Response.Write(String.Format(
"Found entity of type {0} with state {1} < br/>",
ObjectContext.GetObjectType(entry.Entity.GetType()).Name,
entry.State));
}
ممکن است شما بخواهید به Entity هایی دسترسی پیدا کنید که تغییر کرده اند برای این روش ما به صورت زیر در برنامه خود عمل کرده ایم.
Response.Write("\nAll modified entities: < br/>");
foreach (var entry in context.ChangeTracker.Entries()
.Where(e => e.State == EntityState.Modified))
{
Response.Write(String.Format(
"Found entity of type {0} with state {1} < br/>",
ObjectContext.GetObjectType(entry.Entity.GetType()).Name,
entry.State));
}
تنها کدی که در بخش بالا نسبت به بخش قبل اضافه شده است کد مربوط به بررسی وضعیت شی های موجود در Context است. با استفاده از این کد زیر ما تنها اشیایی را از Context انتخاب خواهیم کرد که وضعیت آنها به صورت Modified می باشد. خروجی این بخش را نیز مشاهده کنید.
context.ChangeTracker.Entries().Where(e => e.State == EntityState.Modified)
در بخش بعدی ما با استفاده از کد زیر تنها اطلاعات Model مربوط به Ably را واکشی کرده ایم.
context.ChangeTracker.Entries<Ably>()
در این جا چون می دانیم این اشیا چه خصوصیت هایی دارند می توانیم Property های این اشیا را به صورت زیر چاپ کنیم.
Response.Write("\nTracked Ably: ");
foreach (var entry in context.ChangeTracker.Entries<Ably>())
{
Response.Write(String.Format(
"Found Ably {0}: {1} with original Name {2} < br/>",
entry.Entity.Id,
entry.Entity.PostName,
entry.Property(p => p.PostName).OriginalValue));
}
در نهایت با استفاده از کد زیر تمامی Model هایی که از کلاس IPerson ارث می برند را واکشی کرده ایم. همانطور که در ابتدای مقاله مشخص است Model های ما همه از Interface IPerson ارث می برند در نتیجه ما اطلاعات اشیا مربوط به کلاس های Reader و Person را به صورت زیر می توانیم چاپ کنیم و از انجا که می دانیم هر دو این کلاس ها Property با نام Name دارند مقدار این Property را چاپ کرده ایم.
// Find all people (author or reader)
Response.Write("\nPeople: ");
foreach (var entry in context.ChangeTracker.Entries<IPerson>())
{
Response.Write(String.Format("Found Person {0}", entry.Entity.Name));
}
طبیعتا اگر این دستورات در جای خود استفاده شوند می توانند به شما در انجام بسیاری از کارها کمک کنند برای مثال می خواهیم تمامی اطلاعات مربوط به اشیاء Model Ably را که (Property) خصوصیت PostName آنها null است را حذف کنیم.
foreach (var ably in context.Ablies.Local.ToList())
{
if (ably.PostName == null)
{
context.Ablies.Remove(ably);
}
}
در نهایت کافی است که دستور زیر را برای اجرای این تغییرات بر روی پایگاه داده اجرا کنیم.
context.SaveChanges();
همچنین با استفاده از خاصیت ChangeTracker میتوانید گزارشات و کوئری هایی برای بررسی وضعیت اشیا خود بنویسید و یا از این ویژگی برای ساخت کلاس هایی که به صورت Generic می توانند بر روی تمامی Model ها کار کنند ایجاد کنید تا با یک بار کد نویسی بتوانید از کلاس خود برای همه ی پروژه ها و Model ها استفاده کنید.
در بخش بعد در خصوص حالت های EntityState صحبت خواهیم کرد.