کانال بله, جهت پشتیبانی و اطلاع رسانی کانال بله, جهت پشتیبانی و اطلاع رسانی
عضویت

آموزش کار با Disconnected Entity Graph در Entity Framework Core

آموزش کار با Disconnected Entity Graph در Entity Framework Core

در بخش های قبل یاد گرفتیم که چگونه ChangeTracker به صورت خودکار EntityState هر موجودیت در سناریوی connected را تغییر می دهد. در این بخش درمورد تاثیر متدهای مختلف روی موجودیت اصلی و موجودیت های وابسته یک disconnected entity graph در Entity Framework Core صحبت می کنیم.

Entity Framework Core متدهایی در اختیار می گذارد که نه تنها یک موجودیت را به context اصطلاحا attach می کند، بلکه EntityState هر موجودیت درون یک disconnected entity graph تغییر می دهد.


  • Attach()
  • Entry()
  • Add()
  • Update()
  • Remove()

می خواهیم ببینیم متدهای بالا چگونه EntityState هر موجودیت در یک گراف موجودیت را در Entity Framework Core 2.x تغییر می دهد.

متد Attach()

متدهای DbContext.Attach() DbSet.Attach() گراف موجودیت disconnected تعیین شده را attach می کند و شروع به track آن می کند.

مثال زیر رفتار متد DbContext.Attach() و تاثیر آن روی EntityState هر موجودیت در یک گراف را نشان می دهد:


public static void Main()
{
    var stud = new Student() { //Root entity (empty key)
        Name = "Bill",
        Address = new StudentAddress()  //Child entity (with key value)
        {
            StudentAddressId = 1,
            City = "Seattle",
            Country = "USA"
        },
        StudentCourses = new List< StudentCourse >() {
            new StudentCourse(){  Course = new Course(){ CourseName = "Machine Language" } },//Child entity (empty key)
            new StudentCourse(){  Course = new Course(){  CourseId = 2 } } //Child entity (with key value)
        }
    };
    var context = new SchoolContext();
    context.Attach(stud).State = EntityState.Added;  
    DisplayStates(context.ChangeTracker.Entries());
}
private static void DisplayStates(IEnumerable< EntityEntry > entries)
{
    foreach (var entry in entries)
    {
        Console.WriteLine($"Entity: {entry.Entity.GetType().Name},
                             State: {entry.State.ToString()} ");
    }
}


Output:
Entity: Student, State: Added 
Entity: StudentAddress, State: Unchanged 
Entity: StudentCourse, State: Added 
Entity: Course, State: Added 
Entity: StudentCourse, State: Added 
Entity: Course, State: Unchanged

در مثال بالا، stud یک Instance از گراف موجودیت Student است که حاوی reference هایی به دو موجودیت StudentAddress و StudentCourse است. کد context.Attach(stud).State = EntityState.Added گراف موجودیت stud را به Context اصطلاحا attach می کند و state آن را به Added تغییر می دهد.

متد Attach() ، مقدار EntityState موجودیت root (در اینجا Student) را به Added تغییر می دهد، چه مقدار key داشته باشد چه نداشته باشد. اگر یک موجودیت وابسته حاوی مقداری برای key خود باشد، به صورت Unchanged، و در غیر این صورت با Added نشانه گذاری می شود. خروجی مثال بالا نشان می دهد EntityState برای موجودیت Student به Added ست شده و موجودیت های وابسته آن با مقدار key مناسب Unchanged EntityState دارند و آن هایی که مقدار key ندارند Added state دارند.

جدول زیر رفتار متد Attach() را هنگام تعیین EntityState برای گراف موجودیت هایی که disconnected هستند نشان می دهد:

Attach()
Root entity with Key value
Root Entity with Empty or CLR default value
Child Entity with Key value
Child Entity with empty or CLR default value
context.Attach(entityGraph).State = EntityState.Added
Added
Added
Unchanged
Added
context.Attach(entityGraph).State = EntityState.Modified
Modified
Exception
Unchanged
Added
context.Attach(entityGraph).State = EntityState.Deleted
Deleted
Exception
Unchanged
Added

متد Entry()

متد DbContext.Entry() در EF Core متفاوت از EF 6.x عمل می کند. مثال زیر را در نظر بگیرید:


var student = new Student() { //Root entity (empty key)
    Name = "Bill",
    Address = new StudentAddress()  //Child entity (with key value)
    {
        StudentAddressId = 1,
        City = "Seattle",
        Country = "USA"
    },
    StudentCourses = new List< StudentCourse >() {
            new StudentCourse(){  Course = new Course(){ CourseName="Machine Language" } },//Child entity (empty key)
            new StudentCourse(){  Course = new Course(){  CourseId=2 } } //Child entity (with key value)
        }
};
var context = new SchoolContext();
context.Entry(student).State = EntityState.Modified;
DisplayStates(context.ChangeTracker.Entries());


Output:
Entity: Student, State: Modified

در مثال بالا، کد context.Entry(student).State = EntityState.Modified موجودیت را به context اصطلاحا attach می کند و EntityState تعیین شده را به root entity می دهد، و داشتن یا نداشتن مقدار برای key property آن اهمیت ندارد. تمام موجودیت های وابسته در گراف را نادیده می گیرد و آن ها را attach نمی کند، و EntityState آن ها را نیز تغییر نمی دهد.

جدول زیر رفتارهای مختلف متد DbContext.Entry() را نشان می دهد:

Set EntityState using Entry()
Root entity with Key value
Root Entity with Empty or CLR default value
Child Entities with/out Key value
context.Entry(entityGraph).State = EntityState.Added
Added
Added
Ignored
context.Entry(entityGraph).State = EntityState.Modified
Modified
Modified
Ignored
context.Entry(entityGraph).State = EntityState.Deleted
Deleted
Deleted
Ignored

متد Add()

متدهای DbContext.Add و DbSet.Add یک گراف موجودیت را به context اصطلاحا attach می کنند و EntityState موجودیت root و موجودیت های وابسته آن را به Added تغییر می دهند. داشتن یا نداشتن مقدار برای key property آن ها اهمیت ندارد.


var student = new Student() { //Root entity (with key value)
    StudentId = 1,
    Name = "Bill",
    Address = new StudentAddress()  //Child entity (with key value)
    {
        StudentAddressId = 1,
        City = "Seattle",
        Country = "USA"
    },
    StudentCourses = new List< StudentCourse >() {
            new StudentCourse(){  Course = new Course(){ CourseName="Machine Language" } },//Child entity (empty key)
            new StudentCourse(){  Course = new Course(){  CourseId=2 } } //Child entity (with key value)
        }
};
var context = new SchoolContext();
context.Students.Add(student);
DisplayStates(context.ChangeTracker.Entries())


Output:
Entity: Student, State: Added 
Entity: StudentAddress, State: Added
Entity: StudentCourse, State: Added 
Entity: Course, State: Added 
Entity: StudentCourse, State: Added 
Entity: Course, State: Added

جدول زیر EntityState های ممکن در گراف را هنگام استفاده از متدهای DbContext.Add و DbSet.Add نشان می دهد:

Method
Root entity with/out Key value
Child Entities with/out Key value
DbContext.Add(entityGraph) or DbSet.Add(entityGraph)
Added
Added

Update()

متدهای DbContext.Update() DbSet.Update() یک گراف موجودیت را به context اصطلاحا attach می کنند و EntityState همه ی موجودیت ها در یک گراف را براساس مقدار داشتن key property شان تعیین می کنند. مثال زیر را در نظر بگیرید:


 var student = new Student() { //Root entity (with key value)
    StudentId = 1,
    Name = "Bill",
    Address = new StudentAddress()  //Child entity (with key value)
    {
        StudentAddressId = 1,
        City = "Seattle",
        Country = "USA"
    },
    StudentCourses = new List< StudentCourse >() {
            new StudentCourse(){  Course = new Course(){ CourseName="Machine Language" } },//Child entity (empty key)
            new StudentCourse(){  Course = new Course(){  CourseId=2 } } //Child entity (with key value)
        }
};
var context = new SchoolContext();
context.Update(student);
DisplayStates(context.ChangeTracker.Entries());


Output:
Entity: Student, State: Modified 
Entity: StudentAddress, State: Modified 
Entity: StudentCourse, State: Added 
Entity: Course, State: Added 
Entity: StudentCourse, State: Added 
Entity: Course, State: Modified

در مثال بالا، متد Update() به entity هایی که key property هایشان مقدار دارند، Modified state می دهد و به entity هایی که key property هایشان مقدار ندارند یا مقادیر پیش فرض دارند، Modified state می دهد. Root یا child بودن موجودیت اهمیت ندارد.

متد Remove()

متدهای DbContext.Remove() و DbSet.Remove () مقدار EntityState موجودیت root را به Deleted تغییر می دهد.


var student = new Student() { //Root entity (with key value)
    StudentId = 1,
    Name = "Bill",
    Address = new StudentAddress()  //Child entity (with key value)
    {
        StudentAddressId = 1,
        City = "Seattle",
        Country = "USA"
    },
    StudentCourses = new List< StudentCourse >() {
            new StudentCourse(){  Course = new Course(){ CourseName="Machine Language" } },//Child entity (empty key)
            new StudentCourse(){  Course = new Course(){  CourseId=2 } } //Child entity (with key value)
        }
};
var context = new SchoolContext();
context.Remove(student);
DisplayStates(context.ChangeTracker.Entries());


Output:
Entity: Student, State: Deleted 
Entity: StudentAddress, State: Unchanged
Entity: StudentCourse, State: Added 
Entity: Course, State: Added 
Entity: StudentCourse, State: Added 
Entity: Course, State: Unchanged

جدول زیر رفتار متد Remove() و تاثیر آن روی EntityState هر موجودیت را نشان می دهد:

Remove()
Root entity with Key value
Root Entity with Empty or CLR default value
Child Entities with Key value
Child Entities with Empty Key value
DbContext.Remove(entityGraph) or DbSet.Remove(entityGraph)
Deleted
Exception
Unchanged
Added

در بخش بعد به بحث درمورد متد ChangeTracker.TrackGraph() برای دستکاری هر موجودیت در گراف موجودیت می پردازیم.

1398/06/26 2678 0
نظرات شما

نظرات خود را ثبت کنید...