Sitemap

Change Tracker

4 min readOct 18, 2023

--

Selamlar, Bu makalede Entity Framework Core Change Tracker yapısının nasıl çalıştığından bahsediyor olacağız. Konuya basit seviyede bir örnek ile giriş yapalım ve örnek üzerinden detaylandırmaya çalışalım.

        public async Task<IActionResult> GetProduct(int id = 50)
{
using (var context = new NorthwindContext())
{
var product = await context.Products.FirstOrDefaultAsync(p => p.ProductId == id);
product.ProductName = "Pringles Paprika";
await context.SaveChangesAsync();
return Ok(product);
}
}

Örneği inceleyecek olursak, basit bir update işlemi gerçekleştirdik, dikkat ederseniz kod içersinde UPDATE ile ilgili herhangi bir method çağırımı bulunmamaktadır. Tek yaptığımız değişiklikten sonra SaveChangesAsync(); metodunu çağırmak. Peki Entity Framework Core nesne üzerindeki bu değişikliği nasıl algıladı? Yapılan değişikliğin update işlemi olduğuna ve update sorgusu generate etmesi gerektiğine nasıl karar verdi? Tüm bu soruların cevabı ise Change Tracker yapısıdır.

Change Tracker Nedir?

Entity Framework Core içerisinde bulunan bir takip mekanizmasıdır. Context üzerinden nesneler üzerinden yapılan tüm değişiklikler bu yapı sayesinde takip edilir. Bu takip neticesinde nesne üzerinde yapılan değişikliklerden context haberdar edilir.

 using (var context = new NorthwindContext())
{
var tracker = context.ChangeTracker;
}

State Türleri

  • Detached: Takip yapılmadığı anlamına gelir.
  • Modified: Update
  • Added: Insert
  • Unchanged: Nesne üzerinde değişiklik olmadığını ifade eder.
  • Deleted: Delete

Change Tracker DetectChanges

Context üzerinden bir nesne değişikliğe uğradığında(INSERT,UPDATE,DELETE) arka planda tetiklenen methoddur, context bu method sayesinde uyarılmaktadır. SaveChanges(); metodu çağırıldığında da arka planda bu method tetiklemektedir.

using (var context = new NorthwindContext())
{
var tracker = context.ChangeTracker;
tracker.DetectChanges();
}

AutoDetectChangesEnabled

Press enter or click to view image in full size

Change Tracker içerisinde bulunan bu property, context üzerinde bir takibin yapılıp yapılmayacağını belirlemek için kullanılır. Varsayılan olarak “True” set edilmiştir. Takibi kopartmak istersek değerini “False” olarak set etmek yeterli olacaktır. O dakikadan sonra context üzerinde takip yapılmayacak, nesneler üzerinde değişiklik olsa dahi nesne durumu hep UnChanged olarak kalacaktır.

using (var context = new NorthwindContext())
{
var tracker = context.ChangeTracker;
tracker.AutoDetectChangesEnabled = false;
}

Change Tracker HasChanges

Change Tracker içerisinden gelen bu method ile nesne üzerinde bir değişiklik olup olmadığını kontrol edebiliriz. Değişiklik var ise “True” yok ise “False” dönecektir.

Press enter or click to view image in full size
            using (var context = new NorthwindContext())
{
var tracker = context.ChangeTracker;
var product = await context.Products.FirstOrDefaultAsync(p=> p.ProductId==id);
if (product == null) { return NotFound(new {message="Record Not Found"});}
else
{
var availableState = context.Entry(product).State;
product.ProductName = "Diverso DV1118";
var checkStatusChange = tracker.HasChanges();
var newState=context.Entry(product).State;
}
}

Entries

Tekil veriler ile değil koleksiyonlar ile çalışıyorsak, koleksiyon içersindeki nesneleri elde etmek için bu methodu kullanabiliriz. IEnumerable türünde dönüş yapan bu method her bir nesneyi EntityEntry türünde dönecektir. Bir döngü yardımı ile her bir nesneyi gezip, nesneler üzerinde işlemler yapabiliriz.

           using (var context = new NorthwindContext())
{
var tracker = context.ChangeTracker;
var products = await context.Products.ToListAsync();
var entries=tracker.Entries();
foreach (EntityEntry entry in entries)
{
var product = entry.Entity as Product;
}

}
Press enter or click to view image in full size

Entry ile OriginalValues,CurrentValues Değerlerini Elde Etmek

Bu aşamaya kadar Change Tracker üzerinden gelen method ve propertyleri inceledik. Entries metodu koleksiyonlar ile çalışmamıza imkan sağlarken context içersinden gelen Entry(); metodu ise tekil nesneler üzerinde çalışmamıza imkan sağlamaktadır.

           using (var context = new NorthwindContext())
{
var product = await context.Products.FirstOrDefaultAsync(p => p.ProductId == id);
var entry = context.Entry(product);
var originalValue= entry.OriginalValues.GetValue<string>("ProductName");
product.ProductName = "Outliers";
var newValue= entry.CurrentValues.GetValue<string>("ProductName");
}
Press enter or click to view image in full size

AsNoTracking ile Sorgu Bazında Takibin Kopartılması

Change Tracker mekanizmasının devre dışı bırakılabildiğinden bahsetmiştik. Burada dikkat edilmesi gereken ise yerinde ve ihtiyaç dahilinde bu işlemin yapılmasıdır. Sorgu optimizasyonundan avantaj sağlamasının yanında çetşitli maliyetlerde ortaya çıkarmaktadır. Elde edilecek nesne yada nesneler üzerinde bir değişiklik olmayacağı garanti ise takinin koparılması mantıklı bir kullanım olacaktır.

Get Evren Aktas’s stories in your inbox

Join Medium for free to get updates from this writer.

Takibin koparıldığı ama nesne üzerinde değişiklik olduğu senaryoda ise geliştirici bu değişiklikleri algılanabilmesi için gerekli çalışmayı kendisi yapması gerekecektir. Entity sayısı ve uygulamanın veri kaynağı ile olan ilişkisi arttıkça yönetilmesi zor bir durum haline gelen bu kullanımda, takibin elde edilen verinin
kullanım amacına göre koparılmasına yada koparılmamasına karar vermek gerekmektedir. Bu noktada sorgu bazında takibin koparılması için AsNoTracking(); metodunu kullanabiliriz.

Press enter or click to view image in full size
           using (var context = new NorthwindContext())
{
var product = await context.Products.AsNoTracking().FirstOrDefaultAsync(p => p.ProductId == id);
product.ProductName = $"{id}";
var state = context.Entry(product).State;
}

Görseli inceleyecek olursak, AsNoTracking(); metodu ile sorgu bazında takibin kopartılmasının ardından nesne üzerinde değişiklik yapılmış olsa dahi, nesnenin durumu Detached olarak kalmaktadır. Buda context üzerinde takibin yapılmadığı anlamına gelmektedir.

Beni Linkedin Github Twitter üzerinden takip edebilirsiniz. Bir başka makalede görüşmek üzere. Hoşçakalın :)

--

--

Evren Aktas
Evren Aktas

Written by Evren Aktas

Senior Sofware Developer at Nesine