خب امروز میخوام درباره متد DetectChanges صحبت کنم.
قاعدتا کسایی که این مطلب رو میخونن ، باید حداقل دانش اولیه ای نسبت به Entity Framework (چه full و چه Core) داشته باشند.
خب بریم سراغ بحث اصلی.
قبل از پرداختن به خود DetectChanges ، اول یکم درباره ChangeTracker صحبت کنیم.
کلاس ChangeTracker ، داخل فضای نام Microsoft.EntityFrameworkCore.ChangeTracking قرار گرفته و به ما امکان ردیابی state تمام entity هایی که در حال حاظر در DbContext ما موجود هستن رو میده.
زمانی که ما یک شی رو به context اضافه میکنیم و یا تغییری در اون انجام میدیم و یا حذفش میکینم ، این اعمال ها توسط Track، ChangeTracker میشوند و اگر قبل اینکه SaveChanges انجام بدیم ، Context ما Dispose بشه ، تمام اون تغییرات از بین میرن.
بطور کلی ، ChangeTracker دارای State های زیر هست :
خب.تا همینجا صحبت مقدماتی درباره changeTracker بنظرم کفایت میکنه.بریم سراغ بحث اصلی یعنی متد DetectChanges .
using (var context = new AnotherBlogContext()) { var post = context.Posts .Single(p => p.Title == "My First Post"); post.Title = "My Best Post" context.SaveChanges(); }
کد بالا رو نگاه کنید.یک کوئری روی دیتابیس زده میشه ، یک رکورد از جدول خونده میشه و Title اون رکورد تغییر میکنه و بعدش SaveChanges فراخوانی میشه.
حالا یک سوال مطرح میشه و اونم اینه که ما ، توی Entity هامون (عموما کلاس های poco هستند ) ساختار های Track کردن دیتا قرار ندادیم.چطور متد SaveChanges متوجه میشه که باید چه property هایی رو تغییر بده؟!
انتیتی فریم ورک ، یک snapshot از property های entity هایی که با کوئری از دیتابیس دریافت کرده تهیه میکنه.وقتی متد SaveChanges فراخوانی میشه ،بصورت اتوماتیک متد DetectChanges رو فراخوانی میکنه.این متد ، میاد و تمام entity های داخل Context رو اسکن میکنه و اون ها رو با دیتا های اورجینال وجود در SnapShot مقایسه میکنه.اگر پراپرتی تغییر کرده بود ، متوجه میشه که باید یک کوئری سمت دیتابیس زده بشه.مثلا برای مثال بالا متوجه میشه که Title تغییر کرده و یک کوئری Update سمت دیتابیس باید فرستاده بشه.
البته متد DetectChanges کار بیشتری نسبت به چیزی که در بالا توضیح دادم انجام میده.
using (var context = new AnotherBlogContext()) { context.Blogs.Load(); var post = context.Posts .Single(p => p.Title == "My First Post"); post.Title = "My Best Post" post.BlogId = 7; context.SaveChanges(); }
کد بالا رو در نظر بگیرید. همونطور که صحبت شد ، وقتی SaveChanges فراخوانی میشه ، درون خودش DetectChanges رو فراخوانی میکنه.میبینیم که در بالا ، ابتدا تمام Blogs ها رو Load کردیم و در خط
قبل از BlogId ، SaveChanges رو برابر 7 قرار میدیم.حالا DetectChanges وقتی فراخوانی میشه ، علاوه بر اون کارهایی که قبلا گفتیم ، نگاه میکنه که آیا داخل Context ، یک BlogId با Id برابر 7 وجود داره یا نه.اگر وجود داشت navigation property اون Blog رو به این entity جدید متصل میکنه.در اصل میشه اینطوری گفت که DetectChanges چک میکنه که navigation property ها Update بشن.
آیا DetectChanges کار اضافه و بیهوده ای است؟
اگر Context ما تعداد زیادی Entity داشته باشه و با اون ها کار کنیم، قطعا این مبحث DetectChanges برای ما هزینه هایی خواهد داشت ولی این هزینه در اکثر برنامه های ما ، منجر به تولید گلوگاه برای برنامه نمیشه.
در مقاله بعدی به زودی درباره اینکه دقیقا چه زمانی و چگونه متد DetectChanges فراخوانی میشه صحبت میکنیم.
:)