İstemci ve Sunucu Değerlendirmesi karşılaştırması

Genel bir kural olarak, Entity Framework Core sunucuda bir sorguyu mümkün olduğunca değerlendirmeye çalışır. EF Core, sorgunun bölümlerini istemci tarafında değerlendirebileceği parametrelere dönüştürür. Sorgunun geri kalanı (oluşturulan parametrelerle birlikte), sunucuda değerlendirilecek eşdeğer veritabanı sorgusunu belirlemek için veritabanı sağlayıcısına verilir. EF Core, en üst düzey projeksiyonda kısmi istemci değerlendirmesini destekler (temelde son çağrısı Select()). Sorgudaki en üst düzey projeksiyon sunucuya çevrilemezse EF Core gerekli verileri sunucudan getirir ve istemcide sorgunun kalan bölümlerini değerlendirir. EF Core bir ifade algılarsa, sunucuya çevrilemez üst düzey projeksiyon dışında herhangi bir yerde çalışma zamanı özel durumu oluşturur. Ef Core'un sunucuya çevrilemez olanları nasıl belirlediğini anlamak için bkz . Sorgular nasıl çalışır ?

Dekont

3.0 sürümünden önce, Entity Framework Core sorgunun herhangi bir yerinde istemci değerlendirmesini destekliyor. Daha fazla bilgi için önceki sürümler bölümüne bakın.

Bahşiş

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

Üst düzey projeksiyonda istemci değerlendirmesi

Aşağıdaki örnekte, BIR SQL Server veritabanından döndürülen blogların URL'lerini standartlaştırmak için bir yardımcı yöntemi kullanılır. SQL Server sağlayıcısı bu yöntemin nasıl uygulandığına ilişkin bir içgörüye sahip olmadığından, bunu SQL'e çevirmek mümkün değildir. Sorgunun diğer tüm yönleri veritabanında değerlendirilir, ancak bu yöntem aracılığıyla döndürülen URL geçirildiğinde istemcide yapılır.

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

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

    return url;
}

Desteklenmeyen istemci değerlendirmesi

İstemci değerlendirmesi yararlı olsa da, bazen düşük performansa neden olabilir. Yardımcı yönteminin artık where filtresinde kullanıldığı aşağıdaki sorguyu göz önünde bulundurun. Filtre veritabanına uygulanamadığından, filtrenin istemciye uygulanabilmesi için tüm verilerin belleğe çekilmesi gerekir. Filtreye ve sunucudaki veri miktarına bağlı olarak istemci değerlendirmesi düşük performansa neden olabilir. Bu nedenle Entity Framework Core bu tür istemci değerlendirmelerini engeller ve bir çalışma zamanı özel durumu oluşturur.

var blogs = context.Blogs
    .Where(blog => StandardizeUrl(blog.Url).Contains("dotnet"))
    .ToList();

Açık istemci değerlendirmesi

Aşağıdaki gibi belirli durumlarda açıkça istemci değerlendirmesine zorlamanız gerekebilir

  • Veri miktarı küçüktür, böylece istemcide değerlendirme büyük bir performans cezasına neden olmaz.
  • Kullanılan LINQ işlecinin sunucu tarafı çevirisi yok.

Böyle durumlarda, veya ToList (AsAsyncEnumerable veya ToListAsync zaman uyumsuz için) gibi AsEnumerable yöntemleri çağırarak istemci değerlendirmesini açıkça kabul edebilirsiniz. Kullanarak AsEnumerable sonuçların akışını yaparsınız, ancak kullanmak ToList da ek bellek alan bir liste oluşturarak arabelleğe alma işlemine neden olur. Ancak birden çok kez numaralandırıyorsanız, veritabanında yalnızca bir sorgu olduğundan sonuçların bir listede depolanması daha fazla yardımcı olur. Belirli bir kullanıma bağlı olarak, servis talebi için hangi yöntemin daha yararlı olduğunu değerlendirmeniz gerekir.

var blogs = context.Blogs
    .AsEnumerable()
    .Where(blog => StandardizeUrl(blog.Url).Contains("dotnet"))
    .ToList();

Bahşiş

kullanıyorsanız AsAsyncEnumerable ve sorguyu istemci tarafında daha fazla oluşturmak istiyorsanız, zaman uyumsuz numaralandırılabilir öğeler için işleçleri tanımlayan System.Interactive.Async kitaplığını kullanabilirsiniz. Daha fazla bilgi için bkz . istemci tarafı linq işleçleri.

İstemci değerlendirmesinde olası bellek sızıntısı

Sorgu çevirisi ve derleme pahalı olduğundan EF Core derlenmiş sorgu planını önbelleğe alır. Önbelleğe alınan temsilci, üst düzey projeksiyonun istemci değerlendirmesini yaparken istemci kodunu kullanabilir. EF Core, ağacın istemci tarafından değerlendirilen bölümleri için parametreler oluşturur ve parametre değerlerini değiştirerek sorgu planını yeniden kullanılır. Ancak ifade ağacındaki bazı sabitler parametrelere dönüştürülemez. Önbelleğe alınan temsilci bu tür sabitler içeriyorsa, bunlara başvurulmaya devam ettiğinden bu nesneler çöp olarak toplanamaz. Böyle bir nesne içinde DbContext veya başka hizmetler içeriyorsa, uygulamanın bellek kullanımının zaman içinde artmasına neden olabilir. Bu davranış genellikle bellek sızıntısının bir işaretidir. EF Core, geçerli veritabanı sağlayıcısı kullanılarak eşlenebilen bir tür sabitleriyle karşılaşan bir özel durum oluşturur. Yaygın nedenler ve çözümleri şunlardır:

  • Örnek yöntemi kullanma: İstemci projeksiyonunda örnek yöntemleri kullanılırken, ifade ağacı örneğin sabitini içerir. Yönteminiz örnekten herhangi bir veri kullanmıyorsa, yöntemini statik hale getirebilirsiniz. Yöntem gövdesinde örnek verilerine ihtiyacınız varsa, belirli verileri yönteme bağımsız değişken olarak geçirin.
  • Yönteme sabit bağımsız değişkenleri geçirme: Bu durum genellikle this istemci yöntemine bir bağımsız değişken kullanılarak ortaya çıkar. bağımsız değişkenini veritabanı sağlayıcısı tarafından eşlenebilen birden çok skaler bağımsız değişkene bölmeyi göz önünde bulundurun.
  • Diğer sabitler: Başka bir durumda bir sabitle karşılaşırsanız, işlemde sabitin gerekli olup olmadığını değerlendirebilirsiniz. Sabitin olması gerekiyorsa veya yukarıdaki durumlardan bir çözüm kullanamıyorsanız, değeri depolamak ve sorguda yerel değişkeni kullanmak için yerel bir değişken oluşturun. EF Core, yerel değişkeni bir parametreye dönüştürür.

Önceki sürümler

Aşağıdaki bölüm 3.0 öncesi EF Core sürümleri için geçerlidir.

Eski EF Core sürümleri, yalnızca üst düzey projeksiyonu değil, sorgunun herhangi bir bölümünde istemci değerlendirmesini desteklemektedir. Bu nedenle Desteklenmeyen istemci değerlendirme bölümü altında gönderilen sorguya benzer sorgular doğru şekilde çalıştı. Bu davranış dikkate alınamayan performans sorunlarına neden olabileceğinden EF Core bir istemci değerlendirme uyarısı günlüğe kaydetmiş. Günlük çıkışını görüntüleme hakkında daha fazla bilgi için bkz . Günlüğe kaydetme.

İsteğe bağlı olarak EF Core, istemci değerlendirmesi yaparken (projeksiyon dışında) bir özel durum oluşturacak veya hiçbir şey yapmamak için varsayılan davranışı değiştirmenize izin vermiştir. Özel durum oluşturma davranışı, bunu 3.0'daki davranışa benzer hale getirir. Davranışı değiştirmek için, bağlamınızın seçeneklerini ayarlarken (genellikle içinde DbContext.OnConfiguringveya ASP.NET Core kullanıyorsanız) Startup.cs uyarıları yapılandırmanız gerekir.

protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
    optionsBuilder
        .UseSqlServer(@"Server=(localdb)\mssqllocaldb;Database=EFQuerying;Trusted_Connection=True;")
        .ConfigureWarnings(warnings => warnings.Throw(RelationalEventId.QueryClientEvaluationWarning));
}