EF Core 6.0'daki hataya neden olan değişiklikler
Aşağıdaki API ve davranış değişiklikleri, EF Core 6.0'a güncelleştirilen mevcut uygulamaları bozma potansiyeline sahiptir.
Hedef Çerçeve
EF Core 6.0, .NET 6'yi hedefler. Eski .NET, .NET Core ve .NET Framework sürümlerini hedefleyen uygulamaların EF Core 6.0 kullanmak için .NET 6'yı hedeflemesi gerekir.
Özet
* Bu değişiklikler, veritabanı sağlayıcılarının ve uzantılarının yazarları tarafından özellikle ilgi çekicidir.
Yüksek etkili değişiklikler
Tablo paylaşan ve gerekli özellikleri olmayan iç içe yerleştirilmiş isteğe bağlı bağımlılara izin verilmez
Eski davranış
bir tabloyu paylaşan ve gerekli özellikleri olmayan iç içe yerleştirilmiş isteğe bağlı bağımlı modellere izin verildi, ancak verileri sorgulayıp yeniden kaydederken veri kaybına neden olabilir. Örneğin, aşağıdaki modeli göz önünde bulundurun:
public class Customer
{
public int Id { get; set; }
public string Name { get; set; }
public ContactInfo ContactInfo { get; set; }
}
[Owned]
public class ContactInfo
{
public string Phone { get; set; }
public Address Address { get; set; }
}
[Owned]
public class Address
{
public string House { get; set; }
public string Street { get; set; }
public string City { get; set; }
public string Postcode { get; set; }
}
veya Address
içindeki ContactInfo
özelliklerin hiçbiri gerekli değildir ve tüm bu varlık türleri aynı tabloya eşlenir. İsteğe bağlı bağımlılar için kurallar (gerekli bağımlıların aksine), için ContactInfo
tüm sütunların null olması durumunda sahibi Customer
sorgulanırken örneği ContactInfo
oluşturulmayacak olduğunu söyler. Ancak bu, sütunlar null olmasa bile örneğinin Address
Address
oluşturulacağı anlamına da gelir.
Yeni davranış
Bu modeli kullanmaya çalışmak artık aşağıdaki özel durumu oluşturur:
System.InvalidOperationException: Varlık türü 'ContactInfo', varlığın var olup olmadığını belirlemek için gerekli olmayan paylaşılan özellik olmadan tablo paylaşımı ve diğer bağımlıları içeren isteğe bağlı bir bağımlıdır. Tüm null atanabilir özellikler veritabanında null değer içeriyorsa, sorguda iç içe bağımlı değerlerin kaybolmasına neden olan bir nesne örneği oluşturulmaz. Diğer özellikler için null değerlere sahip örnekler oluşturmak için gerekli bir özellik ekleyin veya her zaman örnek oluşturmak için gelen gezintiyi gerekli olarak işaretleyin.
Bu, verileri sorgularken ve kaydederken veri kaybını önler.
Neden?
Tablo paylaşan ve gerekli özellikleri olmayan iç içe isteğe bağlı bağımlı modellerin kullanılması genellikle sessiz veri kaybına neden oldu.
Risk Azaltıcı Etkenler
İsteğe bağlı bağımlıları tablo paylaşırken ve gerekli özellikler olmadan kullanmaktan kaçının. Bunu yapmanın üç kolay yolu vardır:
Bağımlıları gerekli hale getirin. Bu, tüm özellikleri null olsa bile, bağımlı varlığın sorgulandıktan sonra her zaman bir değere sahip olacağı anlamına gelir. Örneğin:
public class Customer { public int Id { get; set; } public string Name { get; set; } [Required] public Address Address { get; set; } }
Veya:
modelBuilder.Entity<Customer>( b => { b.OwnsOne(e => e.Address); b.Navigation(e => e.Address).IsRequired(); });
Bağımlının en az bir gerekli özellik içerdiğinden emin olun.
İsteğe bağlı bağımlıları sorumluyla paylaşmak yerine kendi tablolarıyla eşleyin. Örneğin:
modelBuilder.Entity<Customer>( b => { b.ToTable("Customers"); b.OwnsOne(e => e.Address, b => b.ToTable("CustomerAddresses")); });
EF Core 6.0'daki yenilikler belgelerinde isteğe bağlı bağımlılarla ilgili sorunlar ve bu risk azaltma örnekleri yer alır.
Orta düzeyde etki eden değişiklikler
Sahip olunan bir varlığın sahibini değiştirmek artık bir özel durum oluşturur
Eski davranış
Sahip olunan bir varlığı farklı bir sahip varlığa yeniden atamak mümkündü.
Yeni davranış
Bu eylem şimdi bir özel durum oluşturur:
'{entityType} özelliği. {property}' bir anahtarın parçası olduğundan değiştirilemez veya değiştirilmiş olarak işaretlenemez. Var olan bir varlığın sorumlusunu tanımlayıcı yabancı anahtarla değiştirmek için önce bağımlı öğeyi silin ve 'SaveChanges' öğesini çağırın ve ardından bağımlıyı yeni sorumluyla ilişkilendirin.
Neden?
Sahip olunan bir türde anahtar özellikleri olmasını gerektirmesek de EF, birincil anahtar olarak kullanılacak gölge özellikler ve sahibi işaret eden yabancı anahtar oluşturmaya devam eder. Sahip varlığı değiştirildiğinde, sahip olunan varlıktaki yabancı anahtarın değerlerinin değişmesine neden olur ve birincil anahtar olarak da kullanıldığından varlık kimliğinin değişmesine neden olur. Bu henüz EF Core'da tam olarak desteklenmemektedir ve yalnızca sahip olunan varlıklar için koşullu olarak izin veriliyordu ve bu da bazen iç durumun tutarsız olmasına neden oldu.
Risk Azaltıcı Etkenler
Aynı sahip olunan örneği yeni bir sahipe atamak yerine bir kopya atayabilir ve eskisini silebilirsiniz.
Azure Cosmos DB: İlgili varlık türleri sahip olduğu şekilde bulunur
İzleme Sorunu #24803Yenilikler: Varsayılan olarak örtük sahiplik
Eski davranış
Diğer sağlayıcılarda olduğu gibi, ilgili varlık türleri normal (sahip olunmayan) türler olarak bulundu.
Yeni davranış
İlişkili varlık türleri artık bulundukları varlık türüne ait olacak. Yalnızca bir DbSet<TEntity> özelliğe karşılık gelen varlık türleri sahip olunmayan olarak bulunur.
Neden?
Bu davranış, Azure Cosmos DB'de ilgili verileri tek bir belgeye eklemek için kullanılan veri modelleme desenini izler. Azure Cosmos DB, farklı belgelerin yerel olarak birleştirilmelerini desteklemediğinden, ilgili varlıkların sahip olunmayan varlıklar olarak modellenmesi sınırlı kullanışlılığa sahiptir.
Risk Azaltıcı Etkenler
Bir varlık türünü sahip olunmayan çağrı olacak şekilde yapılandırmak için modelBuilder.Entity<MyEntity>();
SQLite: Bağlantılar havuza alınıyor
İzleme Sorunu #13837Yenilikler: Varsayılan olarak örtük sahiplik
Eski davranış
Daha önce Microsoft.Data.Sqlite'daki bağlantılar havuza alınmıyordu.
Yeni davranış
6.0'dan itibaren bağlantılar varsayılan olarak havuza eklenir. Bu, ADO.NET bağlantı nesnesi kapatıldıktan sonra bile veritabanı dosyalarının işlem tarafından açık tutulmasına neden olur.
Neden?
Temel alınan bağlantıların havuzalanması, ADO.NET bağlantı nesnelerini açma ve kapatma performansını büyük ölçüde artırır. Bu durum özellikle şifreleme durumunda olduğu gibi temel alınan bağlantıyı açmanın pahalı olduğu senaryolarda veya veritabanına çok fazla kısa süreli bağlantının bulunduğu senaryolarda fark edilir.
Risk Azaltıcı Etkenler
Bağlantı havuzu, bir bağlantı dizesi eklenerek Pooling=False
devre dışı bırakılabilir.
Bazı senaryolar (veritabanı dosyasını silme gibi) artık dosyanın hala kullanımda olduğunu belirten hatalarla karşılaşabilir. kullanarak SqliteConnection.ClearPool()
dosyanın işlemlerini gerçekleştirmeden önce bağlantı havuzunu el ile temizleyebilirsiniz.
SqliteConnection.ClearPool(connection);
File.Delete(databaseFile);
Eşlenmiş birleştirme varlıkları olmayan çoka çok ilişkiler artık yapı iskelesi oluşturulmuş
Eski davranış
Var olan bir veritabanından bir DbContext
ve varlık türlerinin iskelesini oluşturma (tersine mühendislik), çoka çok ilişkiler için varlık türlerini birleştirmek için her zaman açıkça eşlenmiş birleştirme tablolarıdır.
Yeni davranış
Diğer tablolara yalnızca iki yabancı anahtar özelliği içeren basit birleştirme tabloları artık açık varlık türleriyle eşlenmez, bunun yerine birleştirilen iki tablo arasında çoka çok ilişki olarak eşlenir.
Neden?
Açık birleştirme türleri olmayan çoka çok ilişkiler EF Core 5.0'da kullanıma sunulmuştur ve basit birleştirme tablolarını temsil etmenin daha temiz, daha doğal bir yoludur.
Risk Azaltıcı Etkenler
İki risk azaltma vardır. Tercih edilen yaklaşım, kodu çoka çok ilişkileri doğrudan kullanacak şekilde güncelleştirmektir. Çoka çok ilişkiler için yalnızca iki yabancı anahtar içerdiğinde birleştirme varlık türünün doğrudan kullanılması çok nadirdir.
Alternatif olarak, açık birleştirme varlığı EF modeline geri eklenebilir. Örneğin, ile Tag
arasında Post
çoka çok ilişki olduğunu varsayarsak, kısmi sınıfları kullanarak birleştirme türünü ve gezintileri geri ekleyin:
public partial class PostTag
{
public int PostsId { get; set; }
public int TagsId { get; set; }
public virtual Post Posts { get; set; }
public virtual Tag Tags { get; set; }
}
public partial class Post
{
public virtual ICollection<PostTag> PostTags { get; set; }
}
public partial class Tag
{
public virtual ICollection<PostTag> PostTags { get; set; }
}
Ardından dbContext için kısmi sınıfa birleştirme türü ve gezintiler için yapılandırma ekleyin:
public partial class DailyContext
{
partial void OnModelCreatingPartial(ModelBuilder modelBuilder)
{
modelBuilder.Entity<Post>(entity =>
{
entity.HasMany(d => d.Tags)
.WithMany(p => p.Posts)
.UsingEntity<PostTag>(
l => l.HasOne<Tag>(e => e.Tags).WithMany(e => e.PostTags).HasForeignKey(e => e.TagsId),
r => r.HasOne<Post>(e => e.Posts).WithMany(e => e.PostTags).HasForeignKey(e => e.PostsId),
j =>
{
j.HasKey("PostsId", "TagsId");
j.ToTable("PostTag");
});
});
}
}
Son olarak, yapı iskelesi oluşturulan bağlamdan çoka çok ilişkisi için oluşturulan yapılandırmayı kaldırın. Açık türün kullanılabilmesi için önce yapı iskelesi oluşturulmuş birleştirme varlık türünün modelden kaldırılması gerektiğinden bu gereklidir. Bağlam her iskeleye eklendiğinde bu kodun kaldırılması gerekir, ancak yukarıdaki kod kısmi sınıflarda olduğundan kalıcı olur.
Bu yapılandırmayla, birleştirme varlığının EF Core'un önceki sürümlerinde olduğu gibi açıkça kullanılabileceğini unutmayın. Ancak, ilişki çoka çok ilişki olarak da kullanılabilir. Bu, kodun bu şekilde güncelleştirilmesinin geçici bir çözüm olabileceği, ancak kodun geri kalanının ilişkiyi çoka çok olarak doğal bir şekilde kullanacak şekilde güncelleştirildiği anlamına gelir.
Düşük etkili değişiklikler
DeleteBehavior ile ON DELETE değerleri arasındaki eşleme temizlendi
Eski davranış
Bir ilişkinin OnDelete()
davranışı ile veritabanındaki yabancı anahtarların ON DELETE
davranışı arasındaki eşlemelerin bazıları hem Geçişler hem de yapı iskelesi açısından tutarsızdı.
Yeni davranış
Aşağıdaki tabloda Geçişler için yapılan değişiklikler gösterilmektedir.
OnDelete() | SİlDİKİNDE |
---|---|
NoAction | EYLEM YOK |
ClientNoAction | EYLEM YOK |
Sınırla | SINIRLAMAK |
Cascade | ÇAĞLAYAN |
ClientCascade | |
SetNull | SET NULL |
ClientSetNull |
yapı iskelesi değişiklikleri aşağıdaki gibidir.
SİlDİKİNDE | OnDelete() |
---|---|
EYLEM YOK | ClientSetNull |
SINIRLAMAK | |
ÇAĞLAYAN | Cascade |
SET NULL | SetNull |
Neden?
Yeni eşlemeler daha tutarlıdır. EYLEM YOK varsayılan veritabanı davranışı artık daha kısıtlayıcı ve daha az performanslı RESTRICT davranışı yerine tercih edilir.
Risk Azaltıcı Etkenler
İsteğe bağlı ilişkilerin varsayılan OnDelete() davranışı ClientSetNull'dır. Eşlemesi RESTRICT olan EYLEM YOK olarak değiştirildi. Bu, EF Core 6.0'a yükselttikten sonra eklenen ilk geçişinizde çok fazla işlem oluşturulmasına neden olabilir.
EF Core üzerinde işlevsel bir etkisi olmadığından bu işlemleri uygulamayı veya geçişten el ile kaldırmayı seçebilirsiniz.
SQL Server RESTRICT'i desteklemediğinden, bu yabancı anahtarlar EYLEM YOK kullanılarak zaten oluşturulmuştur. Geçiş işlemlerinin SQL Server üzerinde hiçbir etkisi olmayacaktır ve kaldırılmaları güvenlidir.
Bellek içi veritabanı gerekli özelliklerin null içermediğini doğrular
Eski davranış
Bellek içi veritabanı, özellik gerektiği gibi yapılandırıldığında bile null değerlerin kaydedilmesine izin verdi.
Yeni davranış
Bellek içi veritabanı, veya SaveChangesAsync
çağrıldığında SaveChanges
bir Microsoft.EntityFrameworkCore.DbUpdateException
oluşturur ve gerekli bir özellik null olarak ayarlanır.
Neden?
Bellek içi veritabanı davranışı artık diğer veritabanlarının davranışıyla eşleşir.
Risk Azaltıcı Etkenler
Bellek içi sağlayıcı yapılandırılırken önceki davranış (null değerlerin denetlenmemesi) geri yüklenebilir. Örneğin:
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
optionsBuilder
.UseInMemoryDatabase("MyDatabase", b => b.EnableNullChecks(false));
}
Koleksiyonlara katılırken son ORDER BY kaldırıldı
Eski davranış
Koleksiyonlarda SQL JOIN'leri gerçekleştirirken (bire çok ilişkiler), EF Core, birleştirilen tablonun her anahtar sütunu için ORDER BY eklemek için kullanılır. Örneğin, tüm Blogları ilgili Gönderileriyle yükleme işlemi aşağıdaki SQL aracılığıyla yapılmıştır:
SELECT [b].[BlogId], [b].[Name], [p].[PostId], [p].[BlogId], [p].[Title]
FROM [Blogs] AS [b]
LEFT JOIN [Post] AS [p] ON [b].[BlogId] = [p].[BlogId]
ORDER BY [b].[BlogId], [p].[PostId]
Bu sıralamalar varlıkların düzgün bir şekilde gerçekleştirilmesi için gereklidir.
Yeni davranış
Koleksiyon birleştirmesi için son ORDER BY artık atlanıyor:
SELECT [b].[BlogId], [b].[Name], [p].[PostId], [p].[BlogId], [p].[Title]
FROM [Blogs] AS [b]
LEFT JOIN [Post] AS [p] ON [b].[BlogId] = [p].[BlogId]
ORDER BY [b].[BlogId]
Post'un Kimlik sütunu için ORDER BY artık oluşturulmaz.
Neden?
Her ORDER BY veritabanı tarafında ek çalışma uygular ve EF Core'un gerçekleştirme gereksinimleri için son sıralama gerekli değildir. Veriler, bu son sıralamanın kaldırılmasının bazı senaryolarda önemli bir performans artışına neden olabileceğini gösterir.
Risk Azaltıcı Etkenler
Uygulamanız birleştirilmiş varlıkların belirli bir sırada döndürülmesini bekliyorsa, sorgunuza bir LINQ OrderBy
işleci ekleyerek bunu açık hale getirin.
DbSet artık IAsyncEnumerable uygulamaz
Eski davranış
DbSet<TEntity>, DbContext'te sorguları yürütmek için kullanılır ve uygulamak IAsyncEnumerable<T>için kullanılır.
Yeni davranış
DbSet<TEntity> artık doğrudan uygulamaz IAsyncEnumerable<T>.
Neden?
DbSet<TEntity>başlangıçta temel olarak yapı aracılığıyla foreach
üzerinde doğrudan numaralandırmaya izin vermek için uygulanacak IAsyncEnumerable<T> şekilde yapılmıştır. Ne yazık ki, bir proje zaman uyumsuz LINQ işleçleri istemci tarafı oluşturmak için System.Linq.Async'e de başvurduğunda, bu, üzerinde tanımlanan işleçler ile üzerinde IQueryable<T>
IAsyncEnumerable<T>
tanımlananlar arasında belirsiz bir çağırma hatasına neden oldu. C# 9, başvuru IAsyncEnumerable
için özgün ana nedeni kaldırarak döngüler için foreach
uzantı GetEnumerator
desteği ekledi.
LINQ işleçlerini üzerinde DbSet
oluşturduğundan, kullanımların büyük çoğunluğu DbSet
olduğu gibi çalışmaya devam edecektir. Bozuk olan tek kullanımlar doğrudan 'a IAsyncEnumerable
atama DbSet
girişiminde bulunanlardır.
Risk Azaltıcı Etkenler
olarak başvurmanız DbSet<TEntity> IAsyncEnumerable<T>gerekiyorsa, açıkça yayına almak için çağrısı DbSet<TEntity>.AsAsyncEnumerable yapın.
TVF dönüş varlık türü de varsayılan olarak bir tabloya eşlenir
Eski davranış
ile yapılandırılmış bir TVF'nin dönüş türü olarak kullanıldığında, varlık türü varsayılan olarak bir tabloya HasDbFunctioneşlenmedi.
Yeni davranış
TVF'nin dönüş türü olarak kullanılan varlık türü varsayılan tablo eşlemesini korur.
Neden?
TVF yapılandırmasının dönüş varlık türü için varsayılan tablo eşlemesini kaldırması sezgisel değildir.
Risk Azaltıcı Etkenler
Varsayılan tablo eşlemesini kaldırmak için öğesini çağırın ToTable(EntityTypeBuilder, String):
modelBuilder.Entity<MyEntity>().ToTable((string?)null));
Kısıtlama adı benzersizliğini denetleme işlemi artık doğrulandı
Eski davranış
Aynı ada sahip kısıtlamaların aynı tabloda bildirilmesine ve kullanılmasına izin verilip verilmedığını denetleyin.
Yeni davranış
Aynı tabloda aynı ada sahip iki denetim kısıtlamasını açıkça yapılandırmak artık bir özel durumla sonuçlanır. Kural tarafından oluşturulan denetim kısıtlamalarına benzersiz bir ad atanır.
Neden?
Veritabanlarının çoğu aynı tabloda aynı ada sahip iki denetim kısıtlamasının oluşturulmasına izin vermez ve bazıları tablolar arasında bile benzersiz olmasını gerektirir. Bu, bir geçiş uygulanırken özel durum oluşturmayla sonuçlanır.
Risk Azaltıcı Etkenler
Bazı durumlarda, bu değişiklik nedeniyle geçerli denetim kısıtlaması adları farklı olabilir. İstenen adı açıkça belirtmek için öğesini çağırın HasName:
modelBuilder.Entity<MyEntity>().HasCheckConstraint("CK_Id", "Id > 0", c => c.HasName("CK_MyEntity_Id"));
IReadOnly Meta Veri arabirimleri eklendi ve uzantı yöntemleri kaldırıldı
Eski davranış
Üç meta veri arabirimi kümesi vardı: IModelve IMutableModel IConventionModel ve uzantı yöntemleri.
Yeni davranış
Yeni bir arabirim kümesi IReadOnly
eklendi, örneğin. IReadOnlyModel Meta veri arabirimleri için daha önce tanımlanmış olan uzantı yöntemleri varsayılan arabirim yöntemlerine dönüştürülmüştür.
Neden?
Varsayılan arabirim yöntemleri uygulamanın geçersiz kılınmasına olanak sağlar; bu, daha iyi performans sunmak için yeni çalışma zamanı modeli uygulaması tarafından yararlanılır.
Risk Azaltıcı Etkenler
Bu değişiklikler çoğu kodu etkilememelidir. Ancak, uzantı yöntemlerini statik çağırma söz dizimi aracılığıyla kullanıyorsanız, örnek çağırma söz dizimine dönüştürülmesi gerekirdi.
IExecutionStrategy artık tek bir hizmettir
Yeni davranış
IExecutionStrategy artık tek bir hizmettir. Bu, özel uygulamalarda eklenen tüm durumların yürütmeler arasında kalacağı ve geçirilen ExecutionStrategy temsilcinin yalnızca bir kez yürütüleceği anlamına gelir.
Neden?
Bu, EF'teki iki sık erişimli yolda ayırmaları azaltmış.
Risk Azaltıcı Etkenler
'den ExecutionStrategy türetilen uygulamalar içindeki OnFirstExecution()herhangi bir durumu temizlemelidir.
geçirilen ExecutionStrategy temsilcideki koşullu mantık özel IExecutionStrategyuygulamasına taşınmalıdır.
SQL Server: Daha fazla hata geçici olarak kabul edilir
Yeni davranış
Yukarıdaki sorunda listelenen hatalar artık geçici olarak kabul edilir. Varsayılan (yeniden denenmeyen) yürütme stratejisi kullanılırken, bu hatalar artık ek bir özel durum örneğine sarmalanır.
Neden?
Hem kullanıcılardan hem de SQL Server ekibinden hataların geçici olarak kabul edilmesi gereken geri bildirimlerini toplamaya devam ediyoruz.
Risk Azaltıcı Etkenler
Geçici olarak kabul edilen hata kümesini değiştirmek için Bağlantı Dayanıklılığı - EF Core'dan SqlServerRetryingExecutionStrategy - türetilebilen özel bir yürütme stratejisi kullanın.
Azure Cosmos DB: 'id' değerlerinde daha fazla karakterden kaçınılır
Eski davranış
EF Core 5'te yalnızca '|'
değerlerde id
kaçış yapıldı.
Yeni davranış
EF Core 6'da , '/'
'\'
'?'
ve '#'
değerleri de id
kaçıştır.
Neden?
Bu karakterler, Resource.Id belgelendiği gibi geçersizdir. bunları içinde id
kullanmak sorguların başarısız olmasına neden olur.
Risk Azaltıcı Etkenler
Varlık olarak Added
işaretlenmeden önce ayarlayarak oluşturulan değeri geçersiz kılabilirsiniz:
var entry = context.Attach(entity);
entry.Property("__id").CurrentValue = "MyEntity|/\\?#";
entry.State = EntityState.Added;
Bazı Singleton hizmetleri artık Kapsamlı
Yeni davranış
Olarak kaydedilen Singleton
birçok sorgu hizmeti ve bazı tasarım zamanı hizmetleri olarak kaydedilir Scoped
.
Neden?
Sorguları etkilemek için yeni bir özelliğe DefaultTypeMapping izin vermek için yaşam süresi değiştirilmelidir.
Tasarım zamanı hizmetlerinin kullanım ömrü, her ikisini de kullanırken oluşan hataları önlemek için çalışma zamanı hizmet ömrüyle eşleşecek şekilde ayarlanmıştır.
Risk Azaltıcı Etkenler
EF Core hizmetlerini varsayılan yaşam süresiyle kaydetmek için kullanın TryAdd . Yalnızca EF tarafından eklenmeyen hizmetler için kullanın TryAddProviderSpecificServices .
Hizmetleri ekleyen veya değiştiren uzantılar için yeni önbelleğe alma API'si
Eski davranış
EF Core 5'te döndürüldü GetServiceProviderHashCode long
ve doğrudan hizmet sağlayıcısı için önbellek anahtarının bir parçası olarak kullanıldı.
Yeni davranış
GetServiceProviderHashCode şimdi döndürür int
ve yalnızca hizmet sağlayıcısı için önbellek anahtarının karma kodunu hesaplamak için kullanılır.
Ayrıca, ShouldUseSameServiceProvider geçerli nesnenin aynı hizmet yapılandırmasını temsil edip etmediğini ve bu nedenle aynı hizmet sağlayıcısını kullanıp kullanamayacağını belirtmek için uygulanması gerekir.
Neden?
Önbellek anahtarının bir parçası olarak karma kodun kullanılması, zaman zaman tanılaması ve düzeltilmesi zor olan çakışmalara neden oldu. Ek yöntem, aynı hizmet sağlayıcısının yalnızca uygun olduğunda kullanılmasını sağlar.
Risk Azaltıcı Etkenler
Birçok uzantı kayıtlı hizmetleri etkileyen hiçbir seçeneği sunmaz ve aşağıdaki uygulamasını ShouldUseSameServiceProviderkullanabilir:
private sealed class ExtensionInfo : DbContextOptionsExtensionInfo
{
public ExtensionInfo(IDbContextOptionsExtension extension)
: base(extension)
{
}
...
public override bool ShouldUseSameServiceProvider(DbContextOptionsExtensionInfo other)
=> other is ExtensionInfo;
}
Aksi takdirde, tüm ilgili seçenekleri karşılaştırmak için ek koşul eklenmelidir.
Yeni anlık görüntü ve tasarım zamanı modeli başlatma yordamı
Eski davranış
EF Core 5'te, anlık görüntü modeli kullanılmaya hazır olmadan önce belirli kuralların çağrılmaya ihtiyacı vardı.
Yeni davranış
IModelRuntimeInitializer gerekli adımlardan bazılarını gizlemek için kullanıma sunulmuştur ve tüm geçiş meta verilerine sahip olmayan bir çalışma zamanı modeli kullanıma sunulmuştur, bu nedenle model farkları için tasarım zamanı modeli kullanılmalıdır.
Neden?
IModelRuntimeInitializer model sonlandırma adımlarını soyutlar, bu nedenle artık kullanıcılar için daha fazla hataya neden olan değişiklikler olmadan değiştirilebilir.
İyileştirilmiş çalışma zamanı modeli, çalışma zamanı performansını geliştirmek için kullanıma sunulmuştur. Çalışma zamanında kullanılmayan meta verileri kaldıran çeşitli iyileştirmeleri vardır.
Risk Azaltıcı Etkenler
Aşağıdaki kod parçacığında, geçerli modelin anlık görüntü modelinden farklı olup olmadığının nasıl denetlendiği gösterilmektedir:
var snapshotModel = migrationsAssembly.ModelSnapshot?.Model;
if (snapshotModel is IMutableModel mutableModel)
{
snapshotModel = mutableModel.FinalizeModel();
}
if (snapshotModel != null)
{
snapshotModel = context.GetService<IModelRuntimeInitializer>().Initialize(snapshotModel);
}
var hasDifferences = context.GetService<IMigrationsModelDiffer>().HasDifferences(
snapshotModel?.GetRelationalModel(),
context.GetService<IDesignTimeModel>().Model.GetRelationalModel());
Bu kod parçacığı, bir modeli harici olarak oluşturup çağırarak UseModelnasıl uygulanacaklarını IDesignTimeDbContextFactory<TContext> gösterir:
internal class MyDesignContext : IDesignTimeDbContextFactory<MyContext>
{
public TestContext CreateDbContext(string[] args)
{
var optionsBuilder = new DbContextOptionsBuilder();
optionsBuilder.UseSqlServer(Configuration.GetConnectionString("DB"));
var modelBuilder = SqlServerConventionSetBuilder.CreateModelBuilder();
CustomizeModel(modelBuilder);
var model = modelBuilder.Model.FinalizeModel();
var serviceContext = new MyContext(optionsBuilder.Options);
model = serviceContext.GetService<IModelRuntimeInitializer>().Initialize(model);
return new MyContext(optionsBuilder.Options);
}
}
OwnedNavigationBuilder.HasIndex
şimdi farklı bir tür döndürür
Eski davranış
EF Core 5'te, HasIndex burada TEntity
sahip türü döndürülürIndexBuilder<TEntity>
.
Yeni davranış
HasIndex şimdi döndürür IndexBuilder<TDependentEntity>
, burada TDependentEntity
sahip olunan türdür.
Neden?
Döndürülen oluşturucu nesnesi doğru yazılmadı.
Risk Azaltıcı Etkenler
Derlemenizi EF Core'un en son sürümüne göre yeniden derlemek, bu değişikliğin neden olduğu sorunları düzeltmek için yeterli olacaktır.
DbFunctionBuilder.HasSchema(null)
Geçersiz kılınır [DbFunction(Schema = "schema")]
Eski davranış
EF Core 5'te, değerle null
çağrılması HasSchema yapılandırma kaynağını DbFunctionAttribute depolamadığından geçersiz kılabildi.
Yeni davranış
Değeriyle null
çağırmak HasSchema artık yapılandırma kaynağını depolar ve özniteliğin bunu geçersiz kılmasını engeller.
Neden?
API ile ModelBuilder belirtilen yapılandırma, veri ek açıklamaları tarafından geçersiz kılınamaz.
Risk Azaltıcı Etkenler
özniteliğinin HasSchema
şemayı yapılandırmasına izin vermek için çağrıyı kaldırın.
Önceden başlatılan gezintiler, veritabanı sorgularından alınan değerler tarafından geçersiz kılındı
Eski davranış
Boş bir nesneye ayarlanmış gezinti özellikleri, izleme sorguları için değiştirilmeden bırakıldı, ancak takip etmeyen sorgular için üzerine yazıldı. Örneğin, aşağıdaki varlık türlerini göz önünde bulundurun:
public class Foo
{
public int Id { get; set; }
public Bar Bar { get; set; } = new(); // Don't do this.
}
public class Bar
{
public int Id { get; set; }
}
Veritabanından sorgulanan varlığa ayarlamak Foo.Bar
için Foo
Bar
izleme yok sorgusu. Örneğin, bu kod:
var foo = context.Foos.AsNoTracking().Include(e => e.Bar).Single();
Console.WriteLine($"Foo.Bar.Id = {foo.Bar.Id}");
Yazdırıldı Foo.Bar.Id = 1
.
Ancak, izleme için aynı sorgu çalıştırması veritabanından sorgulanan varlığın üzerine yazmadı Foo.Bar
. Örneğin, bu kod:
var foo = context.Foos.Include(e => e.Bar).Single();
Console.WriteLine($"Foo.Bar.Id = {foo.Bar.Id}");
Yazdırıldı Foo.Bar.Id = 0
.
Yeni davranış
EF Core 6.0'da sorguları izleme davranışı artık izleme olmayan sorgular ile eşleşir. Bu, bu kodun her ikisinin de olduğu anlamına gelir:
var foo = context.Foos.AsNoTracking().Include(e => e.Bar).Single();
Console.WriteLine($"Foo.Bar.Id = {foo.Bar.Id}");
Ve bu kod:
var foo = context.Foos.Include(e => e.Bar).Single();
Console.WriteLine($"Foo.Bar.Id = {foo.Bar.Id}");
yazdırın Foo.Bar.Id = 1
.
Neden?
Bu değişikliği yapmanın iki nedeni vardır:
- İzleme ve izleme olmayan sorguların tutarlı davranışa sahip olduğundan emin olmak için.
- Bir veritabanı sorgulandığında, uygulama kodunun veritabanında depolanan değerleri geri almak istediğini varsaymak mantıklıdır.
Risk Azaltıcı Etkenler
İki azaltma vardır:
- Veritabanından sonuçlara dahil edilmemesi gereken nesneleri sorgulamayın. Örneğin, yukarıdaki kod parçacıklarında örneğin veritabanından
Bar
döndürülmemesi ve sonuçlara dahil edilmesi gerekip gerekmediğini kullanmayın.Include
Foo.Bar
- Veritabanından sorguladıktan sonra gezintinin değerini ayarlayın. Örneğin, yukarıdaki kod parçacıklarında sorguyu çalıştırdıktan sonra çağırın
foo.Bar = new()
.
Ayrıca, ilgili varlık örneklerini varsayılan nesnelere başlatmamayı göz önünde bulundurun. Bu, ilgili örneğin anahtar değeri ayarlanmadan veritabanına kaydedilmeyen yeni bir varlık olduğunu gösterir. Bunun yerine ilgili varlık veritabanında mevcutsa, koddaki veriler temelde veritabanında depolanan verilerle çelişiyor demektir.
Veritabanındaki bilinmeyen sabit listesi dizesi değerleri sorgulandığında sabit listesi varsayılan değerine dönüştürülmez
Eski davranış
Sabit listesi özellikleri veya EnumToStringConverter
kullanılarak HasConversion<string>()
veritabanındaki dize sütunlarına eşlenebilir. Bu, EF Core'un sütundaki dize değerlerini .NET sabit listesi türünün eşleşen üyelerine dönüştürmesine neden olur. Ancak, dize değeri eşleşmediyse ve sabit listesi üyesiyse, özellik sabit listesi için varsayılan değere ayarlanmıştır.
Yeni davranış
EF Core 6.0 artık "'' dize değeri veritabanından eşlenen '{value}
{enumType}
' sabit dosyasındaki herhangi bir değere dönüştürülemiyor" iletisiyle bir InvalidOperationException
oluşturur.
Neden?
Varlığın daha sonra veritabanına geri kaydedilmesi durumunda varsayılan değere dönüştürülmesi veritabanı bozulmasına neden olabilir.
Risk Azaltıcı Etkenler
İdeal olarak, veritabanı sütununun yalnızca geçerli değerler içerdiğinden emin olun. Alternatif olarak, eski davranışla bir ValueConverter
uygulayın.
DbFunctionBuilder.HasTranslation artık işlev bağımsız değişkenlerini IReadOnlyCollection yerine IReadOnlyList olarak sağlıyor
Eski davranış
yöntemi kullanılarak HasTranslation
kullanıcı tanımlı bir işlev için çeviri yapılandırıldığında, işlevin bağımsız değişkenleri olarak IReadOnlyCollection<SqlExpression>
sağlanmıştır.
Yeni davranış
EF Core 6.0'da bağımsız değişkenler olarak sağlanır IReadOnlyList<SqlExpression>
.
Neden?
IReadOnlyList
dizin oluşturucuları kullanmaya izin verdiğinden, bağımsız değişkenlere artık daha kolay erişilir.
Risk Azaltıcı Etkenler
Yok. IReadOnlyList
arabirimini IReadOnlyCollection
uygular, bu nedenle geçişin basit olması gerekir.
Varlık tablo değerli bir işlevle eşlendiğinde varsayılan tablo eşlemesi kaldırılmaz
Eski davranış
Bir varlık tablo değerli bir işleve eşlendiğinde, bir tabloyla varsayılan eşlemesi kaldırılır.
Yeni davranış
EF Core 6.0'da varlık, tablo değerli işlevle de eşlenmiş olsa bile varsayılan eşleme kullanılarak tabloya eşlenir.
Neden?
Varlıkları döndüren tablo değerli işlevler genellikle yardımcı olarak veya tablonun tamamının katı bir değişimi yerine varlık koleksiyonu döndüren bir işlemi kapsüllemek için kullanılır. Bu değişiklik, olası kullanıcı amacına daha uygun olmayı amaçlar.
Risk Azaltıcı Etkenler
Bir tabloya eşleme, model yapılandırmasında açıkça devre dışı bırakılabilir:
modelBuilder.Entity<MyEntity>().ToTable((string)null);
dotnet-ef hedefleri .NET 6
Eski davranış
dotnet-ef komutu bir süredir .NET Core 3.1'i hedeflemiştir. Bu, .NET çalışma zamanının daha yeni sürümlerini yüklemeden aracın daha yeni sürümünü kullanmanıza olanak tanır.
Yeni davranış
EF Core 6.0.6'da dotnet-ef aracı artık .NET 6'yı hedeflemektedir. Aracı yine de .NET ve .NET Core'un eski sürümlerini hedefleyen projelerde kullanabilirsiniz, ancak aracı çalıştırmak için .NET 6 çalışma zamanını yüklemeniz gerekir.
Neden?
.NET 6.0.200 SDK'sı dotnet tool install
, osx-arm64 üzerindeki davranışını güncelleştirerek .NET Core 3.1'i hedefleyen araçlar için bir osx-x64 dolgusu oluşturdu. dotnet-ef için çalışan bir varsayılan deneyimi korumak için bunu .NET 6 hedefine güncelleştirdik.
Risk Azaltıcı Etkenler
.NET 6 çalışma zamanını yüklemeden dotnet-ef çalıştırmak için aracın eski bir sürümünü yükleyebilirsiniz:
dotnet tool install dotnet-ef --version 3.1.*
IModelCacheKeyFactory
uygulamaların tasarım zamanı önbelleğe alma işlemini işlemek için güncelleştirilmiş olması gerekebilir
Eski davranış
IModelCacheKeyFactory
tasarım zamanı modelini çalışma zamanı modelinden ayrı olarak önbelleğe alma seçeneği yoktu.
Yeni davranış
IModelCacheKeyFactory
, tasarım zamanı modelinin çalışma zamanı modelinden ayrı olarak önbelleğe alınmasını sağlayan yeni bir aşırı yüklemeye sahiptir. Bu yöntemin uygulanmaması aşağıdakine benzer bir özel duruma neden olabilir:
System.InvalidOperationException: 'İstenen yapılandırma okuma için iyileştirilmiş modelde depolanmamış, lütfen 'DbContext.GetService<IDesignTimeModel>() kullanın. Model'.'
Neden?
Derlenmiş modellerin uygulanması için tasarım zamanı (modeli oluştururken kullanılır) ve çalışma zamanı (sorgu yürütülürken vb.) modellerinin ayrılması gerekiyordu. Çalışma zamanı kodunun tasarım zamanı bilgilerine erişmesi gerekiyorsa, tasarım zamanı modelinin önbelleğe alınması gerekir.
Risk Azaltıcı Etkenler
Yeni aşırı yüklemeyi uygulayın. Örneğin:
public object Create(DbContext context, bool designTime)
=> context is DynamicContext dynamicContext
? (context.GetType(), dynamicContext.UseIntProperty, designTime)
: (object)context.GetType();
Düzeltme otomatik olarak doldurulacağı için sorgudaki '{navigation}' gezintisi 'Include' tarafından yoksayıldı. Daha sonra 'Ekle' içinde başka gezintiler belirtilirse bunlar yoksayılır. Ekleme ağacına geri dönmek yasaktır.
NavigationBaseIncludeIgnored
artık varsayılan olarak bir hatadır
Eski davranış
Olay CoreEventId.NavigationBaseIncludeIgnored
varsayılan olarak bir uyarı olarak günlüğe kaydedildi.
Yeni davranış
Olay CoreEventId.NavigationBaseIncludeIgnored
varsayılan olarak bir hata olarak günlüğe kaydedilir ve bir özel durum oluşur.
Neden?
Bu sorgu desenlerine izin verilmez, bu nedenle EF Core artık sorguların güncelleştirilmesi gerektiğini belirtmek için oluşturur.
Risk Azaltıcı Etkenler
Olayı bir uyarı olarak yapılandırarak eski davranış geri yüklenebilir. Örnek:
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
=> optionsBuilder.ConfigureWarnings(b => b.Warn(CoreEventId.NavigationBaseIncludeIgnored));