Not
Bu sayfaya erişim yetkilendirme gerektiriyor. Oturum açmayı veya dizinleri değiştirmeyi deneyebilirsiniz.
Bu sayfaya erişim yetkilendirme gerektiriyor. Dizinleri değiştirmeyi deneyebilirsiniz.
C# null atanabilir başvuru türleri (NRT), başvuru türlerinin ek açıklamalarla belirtilmesine olanak tanır ve bu, bir başvuru türünün null içerip içermemesinin geçerli olup olmadığını gösterir. Bu özellikte yeniyseniz, C# belgelerini okuyarak bu özelliği tanımanız önerilir. Yeni proje şablonlarında null atanabilir başvuru türleri varsayılan olarak etkinleştirilir, ancak açıkça kabul edilmediği sürece mevcut projelerde devre dışı kalır.
Bu sayfada EF Core'un null atanabilir başvuru türlerine yönelik desteği tanıtılır ve bunlarla çalışmaya yönelik en iyi yöntemler açıklanır.
Gerekli ve isteğe bağlı özellikler
Gerekli ve isteğe bağlı özelliklerle ilgili ana belgeler ve bunların null atanabilir 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
Mevcut bir projede nullable başvuru türlerini etkinleştirirken dikkatli olun: Daha önce isteğe bağlı olarak yapılandırılan başvuru türü özellikleri, açıkça nullable olarak belirtilmedikçe artık zorunlu olarak yapılandırılacaktır. İlişkisel veritabanı şemasını yönetirken, bu durum veritabanı sütununun null atanabilirliğini değiştiren geçişlerin oluşturulmasına neden olabilir.
Null değer atanamayan öznitelikler ve ilklendirme
Null atanabilir başvuru türleri etkinleştirildiğinde, C# derleyicisi başlatılmamış null atanamaz özellikler için uyarılar verir, çünkü bu özellikler null içerebilir. Sonuç olarak, varlık türlerini yazmanın yaygın yolu aşağıdakiler kullanılamaz:
public class Customer
{
public int Id { get; set; }
// Generates CS8618, uninitialized non-nullable property:
public string Name { get; set; }
}
C# 11 veya üzerini kullanıyorsanız, gerekli üyeler bu soruna mükemmel bir çözüm sağlar:
public required string Name { get; set; }
Derleyici artık kodunuz bir Müşteri örneği oluşturduğunda her zaman Name özelliğini başlattığını garanti eder. Özelliğine eşlenen veritabanı sütunu null atanamaz olduğundan, EF tarafından yüklenen tüm örnekler de her zaman null olmayan bir Ad içerir.
C# uygulamasının eski bir sürümünü kullanıyorsanız Oluşturucu bağlaması, null değer atanamayan özelliklerinizin başlatıldığından emin olmak için alternatif 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ğlama bir seçenek değildir; örneğin gezinti özellikleri bu şekilde başlatılamaz. Bu gibi durumlarda, null-forgiving işlecinin yardımıyla özelliği null olarak başlatmanız yeterlidir (ancak daha fazla ayrıntı için aşağıya bakın):
public Product Product { get; set; } = null!;
Gerekli gezinti özellikleri
Gerekli gezinti özellikleri ek bir zorluk sunar: Belirli bir ana varlık için her zaman bağımlı bulunur, ancak programın o anki gereksinimlerine bağlı olarak belirli bir sorguyla yüklenip yüklenmeyeceği değişebilir (verileri yüklemek için farklı şablonlara bakın). Aynı zamanda, bu, onlara her erişimin null olup olmadığını kontrol etmesini gerektireceğinden ve gezintinin yüklendiği bilindiğinde null olamayacağından, bu özelliklerin null atanabilir hale getirilmesi istenmeyebilir.
Bu bir sorun olmayabilir! Gerekli bir bağımlı düzgün yüklendiği sürece (örneğin aracılığıyla Include), gezinti özelliğine erişildiğinde her zaman null olmayan bir değer döndürüleceği garanti edilir. Öte yandan uygulama, gezintinin nullolup olmadığını denetleyerek ilişkinin yüklenip yüklenmediğini denetlemeyi seçebilir. Bu gibi durumlarda, navigasyonu boş değer atanabilir olarak yapmak mantıklıdır. Bu, bağımlıdan asıla gerekli yönlendirmelerin sağlanması gerektiği anlamına gelir.
- Yüklenmeyen bir gezintiye erişmek bir programcı hatası olarak kabul ediliyorsa, null olamaz olmalıdır.
- Uygulama kodunun ilişkinin yüklenip yüklenmediğini belirlemek için gezinmeyi kontrol etmesi kabul ediliyorsa, null olabilir olmalıdır.
Daha katı bir yaklaşım istiyorsanız, null atanabilir bir yedekleme alanına sahip null atanamaz bir özelliğe sahip olabilirsiniz:
private Address? _shippingAddress;
public Address ShippingAddress
{
set => _shippingAddress = value;
get => _shippingAddress
?? throw new InvalidOperationException("Uninitialized property: " + nameof(ShippingAddress));
}
Gezinti düzgün yüklendiği sürece, bağımlıya özelliği aracılığıyla erişilebilir. Ancak, özelliğine önce ilgili varlık düzgün yüklenmeden erişilirse, API sözleşmesi yanlış kullanıldığından bir InvalidOperationException oluşturulur.
Not
Birden çok ilgili varlık başvurusu içeren koleksiyon gezintileri her zaman null değer atanamaz olmalıdır. Boş bir koleksiyon, ilişkili varlık olmadığı anlamına gelir, ancak listenin hiçbir zaman null olmaması gerekir.
DbContext ve DbSet
EF ile, bağlam türlerinde başlatılmamış DbSet özelliklerine sahip olmak yaygın bir uygulamadır:
public class MyContext : DbContext
{
public DbSet<Customer> Customers { get; set;}
}
Bu genellikle bir derleyici uyarısına neden olsa da EF Core 7.0 ve üzeri bu uyarıyı bastırır, çünkü EF bu özellikleri yansıma yoluyla otomatik olarak başlatır.
EF Core'un eski sürümünde bu soruna aşağıdaki gibi geçici bir çözüm bulabilirsiniz:
public class MyContext : DbContext
{
public DbSet<Customer> Customers => Set<Customer>();
}
Başka bir strateji, null atanamaz otomatik özellikler kullanmak, ancak bunları null olarak başlatarak, derleyici uyarısını susturmak için null-forgiving işlecini (!) kullanmaktır. DbContext temel oluşturucu, tüm DbSet özelliklerinin başlatılmasını ve null değerinin hiçbir zaman bu özelliklerde gözlemlenmemesini sağlar.
Null değeri alabilen ilişkileri dahil etme ve gezinme
İsteğe bağlı ilişkilerle ilgilenirken, gerçek null başvuru özel durumunun mümkün olmadığı derleyici uyarılarıyla karşılaşabilirsiniz. EF Core, LINQ sorgularınızı yürütürken ve çevirirken isteğe bağlı bir ilgili varlık mevcut değilse, bu varlığa herhangi bir erişimin bir istisna fırlatmak yerine basitçe yok sayılacağını garanti eder. Ancak, derleyici bu EF Core garantisinin farkında değildir ve LINQ sorgusu bellekte LINQ to Objects ile yürütülür gibi uyarılar üretir. Sonuç olarak, derleyiciye gerçek null bir değerin mümkün olmadığını bildirmek için null-forgiving işlecinin (!) kullanılması gerekir:
var order = await context.Orders
.Where(o => o.OptionalInfo!.SomeProperty == "foo")
.ToListAsync();
İsteğe bağlı gezintilerde birden çok ilişki düzeyi dahil edildiğinde de benzer bir sorun oluşur:
var order = await context.Orders
.Include(o => o.OptionalInfo!)
.ThenInclude(op => op.ExtraAdditionalInfo)
.SingleAsync();
Kendinizi bunu çok fazla yaparken buluyorsanız ve söz konusu varlık türleri ağırlıklı olarak (veya yalnızca) EF Core sorgularında kullanılıyorsa, gezinti özelliklerini null olamaz hale getirmeyi ve Fluent API veya Veri Açıklamaları aracılığıyla isteğe bağlı olarak yapılandırmayı göz önünde bulundurun. Bu, ilişkiyi isteğe bağlı tutarken tüm derleyici uyarılarını kaldırır; ancak, varlıklarınız EF Core dışından dolaştırılırsa, özellikler null kabul etmez olarak ek açıklama eklense de null değerlerini gözlemleyebilirsiniz.
Eski sürümlerdeki sınırlamalar
EF Core 6.0'ın öncesinde aşağıdaki sınırlamalar uygulanmıştır:
- Genel API yüzeyi null atanabilirlik için anotlanmamıştır, bu da NRT özelliği etkinleştirildiğinde genel API'yi "null-oblivious" hale getirir ve bazen kullanımda zorluk yaratabilir. Bu özellikle EF Core tarafından kullanıma sunulan FirstOrDefaultAsync gibi eşzamanlı olmayan LINQ işleçlerini içerir. Genel API, EF Core 6.0'dan itibaren null edilebilirlik için tam olarak açıklamalarla donatılmıştır.
- Tersine mühendislik işlemi C# 8 null değerlendirilebilir başvuru türlerini (NRT) desteklemedi: EF Core her zaman bu özelliğin kapalı olduğunu varsayarak C# kodu üretti. Örneğin, null atanabilir metin sütunları türündeki alanlar,
stringyerinestring?türünde bir özellik olarak oluşturulmuş ve bir özelliğin gerekli olup olmadığını yapılandırmak için Fluent API’si veya Veri Açıklamaları kullanılmıştır. EF Core'un eski bir sürümünü kullanıyorsanız, yine de otomatik oluşturulan kodu düzenleyebilir ve bunları C# null atanabilirlik açıklamaları ile değiştirebilirsiniz.