Aracılığıyla paylaş


İzleme ve No-Tracking Sorguları Karşılaştırması

"İzleme davranışı, Entity Framework Core'un bir varlık örneğine ait bilgileri değişiklik izleyicisinde tutup tutmayacağını kontrol eder." Bir varlık izlenirse, varlıkta algılanan tüm değişiklikler sırasında SaveChangesveritabanında kalıcı hale gelir. EF Core ayrıca bir izleme sorgusu sonucundaki varlıklar ile değişiklik izleyicisindeki varlıklar arasındaki gezinti özelliklerini de düzeltir.

Uyarı

Anahtarsız varlık türleri hiçbir zaman izlenmez. Bu makalede varlık türlerinden bahsedildiği her yerde, anahtarı tanımlanmış varlık türlerine başvurur.

Tavsiye

Bu makalenin örneğini GitHub'da görüntüleyebilirsiniz.

sorguları izleme

Varsayılan olarak, varlık türlerini döndüren sorgular takip edilir. İzleme sorgusu, varlık örneklerinde yapılan tüm değişikliklerin SaveChanges tarafından kalıcı hale getirildiği anlamına gelir. Aşağıdaki örnekte, blog derecelendirmesindeki değişiklik algılanır ve SaveChanges sırasında veritabanına kaydedilir.

var blog = await context.Blogs.SingleOrDefaultAsync(b => b.BlogId == 1);
blog.Rating = 5;
await context.SaveChangesAsync();

Sonuçlar bir izleme sorgusunda döndürülürken EF Core varlığın zaten bağlamda olup olmadığını denetler. EF Core mevcut bir varlığı bulursa aynı örnek döndürülür ve bu da daha az bellek kullanabilir ve izleme olmayan sorgudan daha hızlı olabilir. EF Core, girdideki varlığın özelliklerinin geçerli ve özgün değerlerinin üzerine veritabanı değerleri yazmaz. Bağlamda bir varlık bulunmazsa, EF Core yeni bir varlık örneği oluşturur ve onu bağlama ekler. Sorgu sonuçları bağlama eklenen ancak henüz veritabanına kaydedilmeyen herhangi bir varlık içermez.

Takip edilmeyen sorgular

İzlemesiz sorgular, sonuçlar salt okunur bir senaryoda kullanıldığında kullanışlıdır. Değişiklik izleme bilgilerini ayarlamaya gerek olmadığından, bunlar genellikle daha hızlı yürütülür. Veritabanından alınan varlıkların güncelleştirilmesi gerekmiyorsa, izleme olmayan sorgu kullanılmalıdır. Bir sorgu, izleme yapılmayacak şekilde ayarlanabilir. İzlememe sorgusu, aynı zamanda yerel değişiklikleri veya eklenen nesneleri göz ardı ederek veritabanındakilere göre sonuç verir.

var blogs = await context.Blogs
    .AsNoTracking()
    .ToListAsync();

Varsayılan izleme davranışı bağlam örneği düzeyinde değiştirilebilir:

context.ChangeTracker.QueryTrackingBehavior = QueryTrackingBehavior.NoTracking;

var blogs = await context.Blogs.ToListAsync();

Sonraki bölümde, izleme olmayan sorgunun izleme sorgusundan daha az verimli olabileceği zamanlar açıklanmaktadır.

Kimlik çözümlemesi

İzleme sorgusu değişiklik izleyicisini kullandığından EF Core, bir izleme sorgusunda kimlik çözümlemesi yapar. Bir varlığı somutlaştırırken EF Core, zaten izleniyorsa aynı varlık örneğini değişiklik izleyicisinden döndürür. Sonuç aynı varlığı birden çok kez içeriyorsa, her oluşum için aynı örnek döndürülür. İzlemesiz sorgular:

  • Değişiklik izleyicisini kullanmayın ve kimlik çözümlemesi yapmayın.
  • Sonuçta aynı varlık birden çok kez bulunsa bile varlığın yeni bir örneğini döndürür.

İzleme ve izleme yapılmaması aynı sorguda birleştirilebilir. Yani, sonuçlarda kimlik çözümlemesi yapan, takip etmeyen bir sorguya sahip olabilirsiniz. Sorgulanabilir işleç gibi AsNoTracking başka bir işleç AsNoTrackingWithIdentityResolution<TEntity>(IQueryable<TEntity>)ekledik. QueryTrackingBehavior sıralamasına eklenen ilişkili bir giriş de bulunmaktadır. Kimlik çözümleme kullanımı için sorgu, izleme olmadan yapılandırıldığında, sorgu sonuçları oluşturulurken arka planda bağımsız bir değişim izleyici kullanılır, böylece her örnek yalnızca bir kez oluşturulur. Bu değişiklik izleyicisi bağlamdakinden farklı olduğundan, sonuçlar bağlam tarafından izlenmez. Sorgu tam olarak numaralandırıldıktan sonra, değişiklik izleyicisi kapsam dışına çıkar ve gerektiği gibi çöp toplanır.

var blogs = await context.Blogs
    .AsNoTrackingWithIdentityResolution()
    .ToListAsync();

Varsayılan izleme davranışını yapılandırma

Kendinizi birçok sorgu için izleme davranışını değiştirirken bulursanız, bunun yerine varsayılanı değiştirmek isteyebilirsiniz:

protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
    optionsBuilder
        .UseSqlServer(@"Server=(localdb)\mssqllocaldb;Database=EFQuerying.Tracking;Trusted_Connection=True;ConnectRetryCount=0")
        .UseQueryTrackingBehavior(QueryTrackingBehavior.NoTracking);
}

Bu, tüm sorgularınızın varsayılan olarak izlenmemesini sağlar. Hâlâ AsTracking ekleyerek belirli sorguları izleyebilirsiniz.

İzleme ve özel projeksiyonlar

Sorgunun sonuç türü bir varlık türü olmasa bile, EF Core varsayılan olarak sonuçta yer alan varlık türlerini izlemeye devam eder. Bir anonim tür döndüren aşağıdaki sorguda, sonuç kümesindeki Blog örneklerinin izleneceği belirlenecek.

var blog = context.Blogs
    .Select(
        b =>
            new { Blog = b, PostCount = b.Posts.Count() });

Sonuç kümesi LINQ bileşiminden gelen varlık türlerini içeriyorsa EF Core bunları izler.

var blog = context.Blogs
    .Select(
        b =>
            new { Blog = b, Post = b.Posts.OrderBy(p => p.Rating).LastOrDefault() });

Sonuç kümesi herhangi bir varlık türü içermiyorsa izleme yapılmaz. Aşağıdaki sorguda, varlıktaki değerlerden bazılarını içeren anonim bir tür döndüreceğiz (ancak gerçek varlık türünün örneği yok). Sorgudan çıkan izlenen varlık yok.

var blog = context.Blogs
    .Select(
        b =>
            new { Id = b.BlogId, b.Url });

EF Core, en üst düzey projeksiyonda istemci değerlendirmesi yapmayı destekler. EF Core, istemci tarafında değerlendirme yapılması için bir varlık örneği oluşturursa, izlenmeye başlar. Burada, varlıkları istemci yöntemine blog ilettiğimiz için EF Core blog örneklerini de izler.

var blogs = await context.Blogs
    .OrderByDescending(blog => blog.Rating)
    .Select(
        blog => new { Id = blog.BlogId, Url = StandardizeUrl(blog) })
    .ToListAsync();
public static string StandardizeUrl(Blog blog)
{
    var url = blog.Url.ToLower();

    if (!url.StartsWith("http://"))
    {
        url = string.Concat("http://", url);
    }

    return url;
}

EF Core, sonuçta yer alan anahtarsız varlık örneklerini izlemez. Ancak EF Core, yukarıdaki kurallara göre bir anahtarla varlık türlerinin diğer tüm örneklerini izler.

Önceki sürümler

3.0 sürümünden önce EF Core izlemenin nasıl yapıldığı konusunda bazı farklılıklara sahipti. Önemli farklar şunlardır:

  • İstemci ve Sunucu Değerlendirmesi sayfasında açıklandığı gibi EF Core, 3.0 sürümünden önceki sorgunun herhangi bir bölümünde istemci değerlendirmesini destekledi. İstemci değerlendirmesi, sonucun parçası olmayan unsurların oluşturulmasına neden oldu. Bu nedenle EF Core, neyin izlenmiş olduğunu algılamak için sonucu analiz etti. Bu tasarımın aşağıdaki gibi bazı farklılıkları vardı:

    • Yansıtmadaki istemci değerlendirmesi, gerçekleştirmeye neden oldu ancak gerçekleştirilmiş varlık örneğini döndürmedi izlenmedi. Aşağıdaki örnek blog varlıklarını takip etmedi.

      var blogs = await context.Blogs
          .OrderByDescending(blog => blog.Rating)
          .Select(
              blog => new { Id = blog.BlogId, Url = StandardizeUrl(blog) })
          .ToListAsync();
      
    • EF Core, belirli durumlarda LINQ bileşiminden çıkan nesneleri izlemedi. Aşağıdaki örnek Post'i takip etmedi.

      var blog = context.Blogs
          .Select(
              b =>
                  new { Blog = b, Post = b.Posts.OrderBy(p => p.Rating).LastOrDefault() });
      
  • Sorgu sonuçları anahtarsız varlık türleri içerdiğinde, sorgunun tamamı izlenmez hale getirildi. Bu, sonuçta bulunan anahtarlara sahip varlık türlerinin de izlenmediğini belirtir.

  • EF Core, izlemesiz sorgularda kimlik çözümlemesi yapmak için kullanılır. Daha önce döndürülmüş varlıkları izlemek için zayıf referanslar kullandı. Bu nedenle, bir sonuç kümesi aynı varlığı birden çok kez içeriyorsa, her oluşum için aynı örneği alırsınız. Aynı kimliğe sahip önceki bir sonuç kapsam dışına çıksa ve çöp toplandıysa, EF Core yeni bir örnek döndürdü.