Boş Değer Değere Sahip Başvuru Türleriyle Çalışma

C# 8' de null değere değiştirilebilir başvuru türleri (NRT)adlı yeni bir özellik tanıtıldı. Bu özellik, başvuru türlerinin null olup olmadığının geçerli olup olmadığını belirterek açıklama ek açıklamalarına olanak sağlar. Bu özelliği yeni başladıysanız, C# belgelerine bakarak bu özelliği tanımanız önerilir.

Bu sayfa, EF Core başvuru türleri için destek sağlar ve onlarla çalışmaya yönelik en iyi yöntemleri açıklar.

Gerekli ve isteğe bağlı özellikler

Gerekli ve isteğe bağlı özelliklerle ilgili ana belgeler ve bunların null değere değiştirilebilir başvuru türleriyle etkileşimi, Gerekli ve İsteğe Bağlı Özellikler sayfasıdır. Öncelikle bu sayfayı okuyarak başlamanız önerilir.

Not

Var olan bir projede null değere değiştirilebilir başvuru türlerini etkinleştirerek dikkatli olun: Önceden isteğe bağlı olarak yapılandırılan başvuru türü özellikleri, açıkça null değere alınamaz olarak açık bir şekilde açıklama ekli olmadığı sürece artık gerekli şekilde yapılandırılır. İlişkisel veritabanı şemasını yöneterek geçişlerin oluşturularak veritabanı sütununu null değerle değiştirmesi sağlanabilir.

Null değerdilemez özellikler ve başlatma

Null değer atılabilir başvuru türleri etkinleştirildiğinde, C# derleyicisi, null değer içermeyecekleri için herhangi bir uninitialized non-nullable özelliği için uyarılar verir. Sonuç olarak, varlık türlerini yazmak için aşağıdaki yaygın yol kullanılamaz:

public class CustomerWithWarning
{
    public int Id { get; set; }

    // Generates CS8618, uninitialized non-nullable property:
    public string Name { get; set; }
}

Oluşturucu bağlaması, null atanamaz özelliklerinizin başlatılmasını sağlamak için kullanışlı bir tekniktir:

public class CustomerWithConstructorBinding
{
    public int Id { get; set; }
    public string Name { get; set; }

    public CustomerWithConstructorBinding(string name)
    {
        Name = name;
    }
}

Ne yazık ki bazı senaryolarda oluşturucu bağlaması bir seçenek değildir; örneğin gezinti özellikleri bu şekilde başlatılamıyor.

Gerekli gezinti özellikleri ek bir zorluk oluşturur: Belirli bir sorumlu için bağımlı her zaman mevcut olsa da, programda bu noktadaki ihtiyaçlara bağlı olarak belirli bir sorgu tarafından yüklenebilir veya yüklenmemiş olabilir ( veri yüklemeye yönelik farklı desenlerebakın). Aynı zamanda, gerekli olsalar bile tüm bunlara erişimi null olarak denetlemeye zorlar ve bu nedenle bu özellikleri null değere değiştirilebilir yapmak istenmeyen bir durumdur.

Bu senaryoların bir yolu, null değere değiştirilebilir bir backing alanına sahip null değere sahip olmayan bir özelliğin sahip olmaktır:

private Address? _shippingAddress;

public Address ShippingAddress
{
    set => _shippingAddress = value;
    get => _shippingAddress
           ?? throw new InvalidOperationException("Uninitialized property: " + nameof(ShippingAddress));
}

Gezinti özelliği null değere sahip olmayan bir özellik olduğu için gerekli bir gezinti yapılandırılır; ve gezinti düzgün bir şekilde yüklendiğinde, bağımlıya özelliği aracılığıyla erişilebilir. Ancak, ilk olarak ilgili varlık düzgün bir şekilde yüklenmiyorsa, API sözleşmesi yanlış kullanılmaya neden olduğu için bir InvalidOperationException oluşturulur. EF'nin özelliğine değil, her zaman arka alana erişen şekilde yapılandırılması gerektiğini unutmayın çünkü kümeyi asıiken bile değeri okuyabiliyor; Bunu nasıl yapacakları hakkında destek alanlarına bakın ve yapılandırmanın doğru olduğundan emin olmak için belirtmeyi göz önünde bulundurabilirsiniz.

Bir terser alternatif olarak, null-forgiving işlecinin (!) yardımıyla özelliğini null olarak başlatmak mümkündür:

public Product Product { get; set; } = null!;

Gerçek bir null değer, bir programlama hatasının sonucu dışında hiçbir zaman gözlemlenmez, örneğin ilgili varlığı önceden düzgün yüklemeden gezinti özelliğine erişme.

Not

Birden çok ilgili varlık için başvurular içeren koleksiyon gezintileri her zaman null değere sahip olmamalıdır. Boş bir koleksiyon, ilgili varlık olmadığını, ancak listenin hiçbir zaman null olması gerektiğini gösterir.

DbContext ve DbSet

Bağlam türlerinde başlatlanmamış DbSet özelliklerine sahip olmak yaygın bir uygulamadır, derleyici artık onlar için uyarılar yayecektir. Bu durum aşağıdaki gibi düzeltebilirsiniz:

public class NullableReferenceTypesContext : DbContext
{
    public DbSet<Customer> Customers => Set<Customer>();
    public DbSet<Order> Orders => Set<Order>();

    protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
        => optionsBuilder
            .UseSqlServer(
                @"Server=(localdb)\mssqllocaldb;Database=EFNullableReferenceTypes;Trusted_Connection=True");
}

Başka bir strateji, null atanamaz otomatik özellikleri kullanmak, ancak derleyici uyarılarını sessizlik için null-forgiving işleci (!) kullanarak null olarak başlatmaktır. DbContext temel oluşturucusu, tüm DbSet özelliklerinin başlatılmasını ve null değerlerin hiçbir zaman gözlemlenmesini sağlar.

İsteğe bağlı ilişkilerle uğraşıyorsanız, gerçek bir null başvuru özel durumu imkansız olduğunda derleyici uyarılarına karşılaşabiliyoruz. LINQ sorgularınızı çevirip yürütürken EF Core, isteğe bağlı bir ilgili varlık yoksa, bu varlıkla ilgili herhangi bir gezintinin, oluşturmak yerine yok sayılacaklarını garanti eder. Ancak, derleyici bu EF Core farkında değildir ve LINQ sorgusu bellekte yürütülürken uyarı oluşturur ve LINQ to Objects. Sonuç olarak, derleyiciye gerçek bir null değerin mümkün olmadığını bildirmek için null-forgiving işlecinin (!) kullanımı gereklidir:

Console.WriteLine(order.OptionalInfo!.ExtraAdditionalInfo!.SomeExtraAdditionalInfo);

İsteğe bağlı gezintilerde birden çok ilişki düzeyi dahil edildiklerinde de benzer bir sorun oluşur:

var order = context.Orders
    .Include(o => o.OptionalInfo!)
    .ThenInclude(op => op.ExtraAdditionalInfo)
    .Single();

Bunu çok fazla yapıyorsanız ve söz konusu varlık türleri ağırlıklı olarak (veya özel olarak) EF Core sorgularında kullanılıyorsa, gezinti özelliklerini null değere sahip olmayan hale getirdiniz ve bunları Fluent API veya Veri Ek Açıklamaları aracılığıyla isteğe bağlı olarak yapılandırmayı göz önünde bulundurabilirsiniz. Bu, ilişkiyi isteğe bağlı tutma sırasında tüm derleyici uyarılarını kaldırır; ancak, varlıklarınız bir EF Core dışından geçirildiyse, özelliklere null değer atılamaz olarak açıklama ek açıklamalı olsa da null değerleri gözlemlebilirsiniz.

Eski sürümlerde sınırlamalar

6.0 EF Core önce aşağıdaki sınırlamalar uygulanır:

  • Genel API yüzeyi null olabilirlik için not ek açıklamalı değildi (genel API "null-oblivious" idi) ve bu da NRT özelliği açıkken bazen kullanmakta zorlanmalarını sağlar. Bu özellikle FirstOrDefaultAsyncgibi EF Core zaman uyumsuz LINQ işleçlerini içerir. Genel API, EF Core 6.0'dan başlayarak null EF Core olarak açıklanabilir.
  • Tersine mühendislik C# 8 null değer atılabilir başvuru türlerini (NRT)desteklemedi: EF Core özelliğin kapalı olduğunu varsayan her zaman oluşturulan C# kodu. Örneğin, null değer atılabilir metin sütunları, bir özelliğin gerekli olup olmadığını yapılandırmak için Fluent API'si veya Veri Ek Açıklamaları ile değil türüne sahip bir özellik stringstring? olarak iskeleye alındı. EF Core'nin eski bir sürümünü kullanıyorsanız, yapı iskelesi olan kodu düzenleyebilir ve bunları C# null olabilirlik ek açıklamalarını değiştirebilirsiniz.