EF Core 3.x'te hataya neden olan değişiklikler
Aşağıdaki API ve davranış değişiklikleri, mevcut uygulamaları 3.x sürümüne yükseltirken bozma potansiyeline sahiptir. Yalnızca veritabanı sağlayıcılarını etkilemesini beklediğimiz değişiklikler sağlayıcı değişiklikleri altında belgelenmiştir.
Özet
Yüksek etkili değişiklikler
LINQ sorguları artık istemcide değerlendirilmez
İzleme Sorunu #14935Ayrıca bkz. sorun #12795
Eski davranış
3.0'ın öncesinde EF Core sorgunun parçası olan bir ifadeyi SQL veya parametreye dönüştüremediğinde, istemcideki ifadeyi otomatik olarak değerlendirdi. Varsayılan olarak, pahalı olabilecek ifadelerin istemci değerlendirmesi yalnızca bir uyarı tetikledi.
Yeni davranış
3.0'dan başlayarak EF Core yalnızca en üst düzey projeksiyondaki ifadelerin (sorgudaki son Select()
çağrı) istemcide değerlendirilmesine izin verir.
Sorgunun başka bir bölümündeki ifadeler SQL veya parametreye dönüştürülemiyorsa, bir özel durum oluşturulur.
Neden?
Sorguların otomatik istemci değerlendirmesi, önemli bölümleri çevrilemese bile birçok sorgunun yürütülmesini sağlar.
Bu davranış, yalnızca üretimde ortaya çıkabilecek beklenmeyen ve zarar verici davranışlara neden olabilir.
Örneğin, çağrıdaki çevrilemez bir Where()
koşul, tablodaki tüm satırların veritabanı sunucusundan aktarılmasına ve filtrenin istemciye uygulanmasına neden olabilir.
Bu durum, tablo geliştirme aşamasında yalnızca birkaç satır içeriyorsa kolayca algılanabilir, ancak uygulama üretim aşamasına geçtiğinde zorlanabilir ve burada tablo milyonlarca satır içerebilir.
İstemci değerlendirme uyarıları da geliştirme sırasında göz ardı etmek çok kolay oldu.
Bunun yanı sıra, otomatik istemci değerlendirmesi belirli ifadeler için sorgu çevirisini iyileştirmenin yayınlar arasında istenmeyen hata değişikliklerine neden olduğu sorunlara yol açabilir.
Risk Azaltıcı Etkenler
Bir sorgu tam olarak çevrilemiyorsa, sorguyu çevrilebilecek bir biçimde yeniden yazın veya , ToList()
veya benzerini kullanarak AsEnumerable()
verileri açıkça istemciye geri getirin ve LINQ-To-Objects kullanılarak daha fazla işlenebilir.
Orta düzeyde etki eden değişiklikler
Entity Framework Core artık ASP.NET Core paylaşılan çerçevesinin bir parçası değil
Eski davranış
ASP.NET Core 3.0'a bir paket başvurusu Microsoft.AspNetCore.App
Microsoft.AspNetCore.All
eklediğinizde, EF Core ve SQL Server sağlayıcısı gibi bazı EF Core veri sağlayıcıları dahil olurdu.
Yeni davranış
3.0'dan başlayarak, ASP.NET Core paylaşılan çerçevesi EF Core veya herhangi bir EF Core veri sağlayıcısı içermez.
Neden?
Bu değişiklik öncesinde EF Core'u almak için uygulamanın Core ve SQL Server ASP.NET hedeflenip hedeflenmediğine bağlı olarak farklı adımlar gerekir. Ayrıca, ASP.NET Core'un yükseltilmesi EF Core'un ve SQL Server sağlayıcısının yükseltilmesine zorlandı ve bu her zaman tercih edilmez.
Bu değişiklikle, EF Core alma deneyimi tüm sağlayıcılarda, desteklenen .NET uygulamalarında ve uygulama türlerinde aynıdır. Geliştiriciler artık EF Core ve EF Core veri sağlayıcılarının ne zaman yükseltilirlerini de denetleyebilir.
Risk Azaltıcı Etkenler
ASP.NET Core 3.0 uygulamasında veya desteklenen diğer herhangi bir uygulamada EF Core kullanmak için, uygulamanızın kullanacağı EF Core veritabanı sağlayıcısına açıkça bir paket başvurusu ekleyin.
EF Core komut satırı aracı dotnet ef artık .NET Core SDK'sının bir parçası değil
Eski davranış
3.0'dan dotnet ef
önce araç .NET Core SDK'sına dahil edildi ve ek adım gerektirmeden herhangi bir projeden komut satırından kullanıma hazırdı.
Yeni davranış
3.0'dan itibaren .NET SDK'sı dotnet ef
aracı içermez, bu nedenle kullanmadan önce yerel veya genel bir araç olarak açıkça yüklemeniz gerekir.
Neden?
Bu değişiklik, EF Core 3.0'ın da her zaman NuGet paketi olarak dağıtıldığı gerçeğiyle tutarlı olarak NuGet üzerinde normal bir .NET CLI aracı olarak dağıtmamıza ve güncelleştirmemize dotnet ef
olanak tanır.
Risk Azaltıcı Etkenler
Geçişleri yönetebilmek veya bir DbContext
iskele oluşturabilmek için genel bir araç olarak yükleyin dotnet-ef
:
dotnet tool install --global dotnet-ef
Ayrıca, bir araç bildirim dosyası kullanarak bunu araç bağımlılığı olarak bildiren bir projenin bağımlılıklarını geri yüklerken de yerel bir araç elde edebilirsiniz.
Düşük etkili değişiklikler
FromSql, ExecuteSql ve ExecuteSqlAsync yeniden adlandırıldı
Önemli
ExecuteSqlCommand
ve ExecuteSqlCommandAsync
kullanım dışıdır. Bunun yerine bu yöntemleri kullanın.
Eski davranış
EF Core 3.0'den önce, bu yöntem adları normal bir dizeyle veya SQL ve parametrelerle ilişkilendirilmesi gereken bir dizeyle çalışmak için aşırı yüklenmişti.
Yeni davranış
EF Core 3.0'dan başlayarak, parametrelerin sorgu dizesinden ayrı olarak geçirildiği parametreli bir sorgu oluşturmak için , ExecuteSqlRaw
ve ExecuteSqlRawAsync
kullanınFromSqlRaw
.
Örneğin:
context.Products.FromSqlRaw(
"SELECT * FROM Products WHERE Name = {0}",
product.Name);
Parametrelerin ilişkilendirilmiş bir sorgu dizesinin parçası olarak geçirildiği parametreli bir sorgu oluşturmak için , ExecuteSqlInterpolated
ve ExecuteSqlInterpolatedAsync
kullanınFromSqlInterpolated
.
Örneğin:
context.Products.FromSqlInterpolated(
$"SELECT * FROM Products WHERE Name = {product.Name}");
Yukarıdaki sorguların her ikisinin de aynı SQL parametreleriyle aynı parametreli SQL'i oluşturacağını unutmayın.
Neden?
Bunun gibi yöntem aşırı yüklemeleri, amaç ilişkilendirilmiş dize yöntemini çağırmakken yanlışlıkla ham dize yöntemini çağırmayı çok kolaylaştırır. Bu, sorguların olması gerekirken parametrelendirilmemesiyle sonuçlanabilir.
Risk Azaltıcı Etkenler
Yeni yöntem adlarını kullanmaya geçin.
Saklı yordamla kullanıldığında FromSql yöntemi oluşturulamıyor
Eski davranış
EF Core 3.0'dan önce FromSql yöntemi, geçirilen SQL'in oluşturulabileceğini algılamaya çalıştı. SQL bir saklı yordam gibi birleştirilebilir olmadığında istemci değerlendirmesi yaptı. Aşağıdaki sorgu, sunucuda saklı yordamı çalıştırarak ve istemci tarafında FirstOrDefault yaparak çalıştı.
context.Products.FromSqlRaw("[dbo].[Ten Most Expensive Products]").FirstOrDefault();
Yeni davranış
EF Core 3.0'dan itibaren EF Core, SQL'i ayrıştırmaya çalışmaz. Dolayısıyla FromSqlRaw/FromSqlInterpolated'dan sonra oluşturuyorsanız EF Core, alt sorguya neden olarak SQL'i oluşturur. Bu nedenle, oluşturma ile saklı yordam kullanıyorsanız geçersiz SQL söz dizimi için bir özel durum alırsınız.
Neden?
EF Core 3.0, burada açıklandığı gibi hataya açık olduğundan otomatik istemci değerlendirmesini desteklemez.
Risk Azaltıcı Etkenler
FromSqlRaw/FromSqlInterpolated içinde bir saklı yordam kullanıyorsanız, bunun üzerine oluşturulamayacağını biliyorsunuz, bu nedenle sunucu tarafında herhangi bir bileşimi önlemek için FromSql yöntemi çağrısından hemen sonra ekleyebilirsiniz AsEnumerable
/AsAsyncEnumerable
.
context.Products.FromSqlRaw("[dbo].[Ten Most Expensive Products]").AsEnumerable().FirstOrDefault();
FromSql yöntemleri yalnızca sorgu köklerinde belirtilebilir
Eski davranış
EF Core 3.0'da FromSql
yöntemi sorgunun herhangi bir yerinde belirtilebilir.
Yeni davranış
EF Core 3.0'dan başlayarak, yeni FromSqlRaw
ve FromSqlInterpolated
yöntemleri (yerine FromSql
) yalnızca sorgu köklerinde, yani doğrudan üzerinde DbSet<>
belirtilebilir. Bunları başka herhangi bir yerde belirtmeye çalışmak bir derleme hatasına neden olur.
Neden?
FromSql
üzerinde dışında herhangi bir DbSet
yerde belirtmenin hiçbir anlamı veya katma değeri yoktu ve belirli senaryolarda belirsizliğe neden olabilir.
Risk Azaltıcı Etkenler
FromSql
çağrıları doğrudan uygulandıkları yere DbSet
taşınmalıdır.
İzlemesiz sorgular artık kimlik çözümlemesi gerçekleştiriyor
Eski davranış
EF Core 3.0'da, belirli bir türe ve kimliğe sahip bir varlığın her oluşumu için aynı varlık örneği kullanılacaktır. Bu, sorguları izleme davranışıyla eşleşir. Örneğin, şu sorgu:
var results = context.Products.Include(e => e.Category).AsNoTracking().ToList();
verilen kategoriyle ilişkili her Product
biri için aynı Category
örneği döndürür.
Yeni davranış
EF Core 3.0'dan başlayarak, döndürülen grafikte farklı yerlerde belirli bir türe ve kimliğe sahip bir varlıkla karşılaşıldığında farklı varlık örnekleri oluşturulur. Örneğin, iki ürün aynı kategoriyle ilişkilendirildiğinde bile yukarıdaki sorgu artık her Product
için yeni Category
bir örnek döndürür.
Neden?
Kimlik çözümlemesi (yani, bir varlığın daha önce karşılaşılan bir varlıkla aynı türe ve kimliğe sahip olduğunu belirlemek) ek performans ve bellek yükü ekler. Bu genellikle ilk etapta izlemesiz sorguların neden kullanıldığının sayacını çalıştırır. Ayrıca, kimlik çözümlemesi bazen yararlı olsa da, varlıkların seri hale getirilip izleme olmayan sorgular için yaygın olan bir istemciye gönderilmesi gerekli değildir.
Risk Azaltıcı Etkenler
Kimlik çözümlemesi gerekiyorsa bir izleme sorgusu kullanın.
Geçici anahtar değerleri artık varlık örneklerine ayarlanmadı
Eski davranış
EF Core 3.0'ın öncesinde, geçici değerler daha sonra veritabanı tarafından oluşturulan gerçek bir değere sahip olacak tüm anahtar özelliklere atanmıştı. Genellikle bu geçici değerler büyük negatif sayılardı.
Yeni davranış
EF Core, 3.0'dan başlayarak geçici anahtar değerini varlığın izleme bilgilerinin bir parçası olarak depolar ve anahtar özelliğinin kendisini değiştirmeden bırakır.
Neden?
Bu değişiklik, daha önce bazı DbContext
örnekler tarafından izlenen bir varlık farklı DbContext
bir örneğe taşındığında geçici anahtar değerlerinin yanlışlıkla kalıcı olmasını önlemek için yapılmıştır.
Risk Azaltıcı Etkenler
Varlıklar arasında ilişki oluşturmak için yabancı anahtarlara birincil anahtar değerleri atayan uygulamalar, birincil anahtarlar depo tarafından oluşturulursa ve durumdaki varlıklara aitse eski davranışa Added
bağlı olabilir.
Bu durum aşağıdakiler tarafından önlenebilir:
- Mağaza tarafından oluşturulan anahtarlar kullanılmıyor.
- Gezinti özelliklerini yabancı anahtar değerleri ayarlamak yerine ilişkileri oluşturacak şekilde ayarlama.
- Varlığın izleme bilgilerinden gerçek geçici anahtar değerlerini alın.
Örneğin,
context.Entry(blog).Property(e => e.Id).CurrentValue
kendisi ayarlanmamış olsablog.Id
bile geçici değeri döndürür.
DetectChanges, depo tarafından oluşturulan anahtar değerlerini kabul eder
Eski davranış
EF Core 3.0'den önce, tarafından DetectChanges
bulunan izlenmeyen Added
bir varlık durumunda izlenir ve çağrıldığında SaveChanges
yeni bir satır olarak eklenir.
Yeni davranış
EF Core 3.0'dan başlayarak, bir varlık oluşturulan anahtar değerlerini kullanıyorsa ve bazı anahtar değerleri ayarlanmışsa varlık durumunda izlenir Modified
.
Bu, varlık için bir satırın var olduğu varsayıldığı ve çağrıldığında SaveChanges
güncelleştirileceği anlamına gelir.
Anahtar değeri ayarlanmamışsa veya varlık türü oluşturulan anahtarları kullanmıyorsa, yeni varlık önceki sürümlerde olduğu gibi Added
yine izlenir.
Neden?
Bu değişiklik, mağaza tarafından oluşturulan anahtarlar kullanılırken bağlantısız varlık graflarıyla çalışmayı kolaylaştırmak ve daha tutarlı hale getirmek için yapılmıştır.
Risk Azaltıcı Etkenler
Bir varlık türü oluşturulan anahtarları kullanacak şekilde yapılandırıldıysa ancak anahtar değerleri yeni örnekler için açıkça ayarlandıysa, bu değişiklik bir uygulamayı bozabilir. Düzeltme, anahtar özelliklerini oluşturulan değerleri kullanmayacak şekilde açıkça yapılandırmaktır. Örneğin, akıcı API ile:
modelBuilder
.Entity<Blog>()
.Property(e => e.Id)
.ValueGeneratedNever();
Veya veri ek açıklamaları ile:
[DatabaseGenerated(DatabaseGeneratedOption.None)]
public string Id { get; set; }
Art arda silme işlemleri artık varsayılan olarak hemen gerçekleşir
Eski davranış
3.0'den önce EF Core basamaklı eylemler (gerekli bir sorumlu silindiğinde veya gerekli bir sorumluyla ilişki kesildiğinde bağımlı varlıkları silme) SaveChanges çağrılana kadar gerçekleşmedi.
Yeni davranış
3.0'dan itibaren EF Core, tetikleme koşulu algılanır algılanmaz basamaklı eylemler uygular.
Örneğin, bir asıl varlığı silmek için çağrılması context.Remove()
, izlenen tüm ilgili gerekli bağımlıların da hemen olarak ayarlanmasına Deleted
neden olur.
Neden?
Bu değişiklik, çağrılmadan önce SaveChanges
hangi varlıkların silineceğinin anlaşılmasının önemli olduğu veri bağlama ve denetim senaryolarına yönelik deneyimi geliştirmek için yapılmıştır.
Risk Azaltıcı Etkenler
Önceki davranış, üzerindeki context.ChangeTracker
ayarlar aracılığıyla geri yüklenebilir.
Örneğin:
context.ChangeTracker.CascadeDeleteTiming = CascadeTiming.OnSaveChanges;
context.ChangeTracker.DeleteOrphansTiming = CascadeTiming.OnSaveChanges;
İlgili varlıkların hevesle yüklenmesi artık tek bir sorguda gerçekleşiyor
Eski davranış
3.0'ın öncesinde, koleksiyon gezintilerini işleçler aracılığıyla Include
hevesle yüklemek, ilişkisel veritabanında her ilgili varlık türü için bir tane olmak üzere birden çok sorgu oluşturulmasına neden oldu.
Yeni davranış
EF Core, 3.0'dan başlayarak ilişkisel veritabanlarında JOIN'lerle tek bir sorgu oluşturur.
Neden?
Tek bir LINQ sorgusu uygulamak için birden çok sorgunun verilmesi, birden çok veritabanı gidiş dönüşünün gerekli olması nedeniyle negatif performans ve her sorgu veritabanının farklı bir durumunu gözlemleyebileceğinden veri tutarlılığı sorunları da dahil olmak üzere çok sayıda soruna neden oldu.
Risk Azaltıcı Etkenler
Teknik olarak bu hataya neden olan bir değişiklik olmasa da, tek bir sorgu koleksiyon gezintilerinde çok fazla sayıda Include
işleç içerdiğinde uygulama performansı üzerinde önemli bir etkiye sahip olabilir. Daha fazla bilgi edinmek ve sorguları daha verimli bir şekilde yeniden yazmak için bu açıklamaya bakın.
**
DeleteBehavior.Restrict daha temiz semantiklere sahip
Eski davranış
3.0'ın öncesinde, DeleteBehavior.Restrict
veritabanında semantik ile Restrict
yabancı anahtarlar oluşturuldu, ancak aynı zamanda iç düzeltmeyi belirgin olmayan bir şekilde değiştirdi.
Yeni davranış
3.0'dan başlayarak, DeleteBehavior.Restrict
EF iç düzeltmesini etkilemeden yabancı anahtarların semantikle Restrict
(yani basamaksız) oluşturulmasını; kısıtlama ihlaline karşı oluşturulmasını sağlar.
Neden?
Bu değişiklik, beklenmeyen yan etkiler olmadan sezgisel bir şekilde kullanım DeleteBehavior
deneyimini geliştirmek için yapılmıştır.
Risk Azaltıcı Etkenler
Önceki davranış kullanılarak DeleteBehavior.ClientNoAction
geri yüklenebilir.
Sorgu türleri varlık türleriyle birleştirilmiştir
Eski davranış
EF Core 3.0'da sorgu türleri, birincil anahtarı yapılandırılmış bir şekilde tanımlamayan verileri sorgulamanın bir yoludur. Başka bir ifadeyle, anahtarlar olmadan varlık türlerini eşlemek için bir sorgu türü (büyük olasılıkla bir görünümden, ancak bir tablodan) kullanılırken, bir anahtar kullanılabilir olduğunda normal bir varlık türü kullanıldı (büyük olasılıkla bir tablodan, ancak muhtemelen bir görünümden).
Yeni davranış
Sorgu türü artık birincil anahtarı olmayan bir varlık türüne dönüşür. Anahtarsız varlık türleri, önceki sürümlerdeki sorgu türleriyle aynı işlevselliğe sahiptir.
Neden?
Bu değişiklik, sorgu türlerinin amacına ilişkin karışıklığı azaltmak için yapılmıştır. Özellikle, anahtarsız varlık türleridir ve bu nedenle doğal olarak salt okunurlardır, ancak yalnızca varlık türünün salt okunur olması gerektiğinden kullanılmamalıdır. Benzer şekilde, bunlar genellikle görünümlere eşlenir, ancak bunun nedeni görünümlerin genellikle anahtarları tanımlamamalarıdır.
Risk Azaltıcı Etkenler
API'nin aşağıdaki bölümleri artık kullanım dışıdır:
ModelBuilder.Query<>()
- Bunun yerineModelBuilder.Entity<>().HasNoKey()
, bir varlık türünün anahtarsız olarak işaretlenmesi için çağrılmaları gerekir. Bu, birincil anahtar beklendiğinde yanlış yapılandırmayı önlemek için yine de kural tarafından yapılandırılmaz, ancak kuralla eşleşmez.DbQuery<>
- Bunun yerineDbSet<>
kullanılmalıdır.DbContext.Query<>()
- Bunun yerineDbContext.Set<>()
kullanılmalıdır.IQueryTypeConfiguration<TQuery>
- Bunun yerineIEntityTypeConfiguration<TEntity>
kullanılmalıdır.
Not
Tüm özellikleri bir varlık olarak ayarlanmış null
null
anahtarsız varlıkları sorgularken 3.x'teki bir sorun nedeniyle, bu sorun senaryonuz için geçerliyse sonuçlarla ilgilenmek null
için mantık da ekleyin.
Sahip olunan tür ilişkileri için yapılandırma API'si değişti
İzleme Sorunu #12444İzleme Sorunu #9148İzleme Sorunu #14153
Eski davranış
EF Core 3.0'den önce, sahip olunan ilişkinin yapılandırması doğrudan veya OwnsMany
çağrısından OwnsOne
sonra gerçekleştirildi.
Yeni davranış
EF Core 3.0'dan başlayarak, artık kullanarak WithOwner()
sahibine bir gezinti özelliği yapılandırmak için akıcı bir API vardır.
Örneğin:
modelBuilder.Entity<Order>.OwnsOne(e => e.Details).WithOwner(e => e.Order);
Sahip ve sahip arasındaki ilişkiyle ilgili yapılandırma artık diğer ilişkilerin nasıl yapılandırıldığına benzer şekilde zincirlenmelidir WithOwner()
.
Sahip olunan türün yapılandırması yine de sonrasında OwnsOne()/OwnsMany()
zincirlenmiş olur.
Örneğin:
modelBuilder.Entity<Order>.OwnsOne(e => e.Details, eb =>
{
eb.WithOwner()
.HasForeignKey(e => e.AlternateId)
.HasConstraintName("FK_OrderDetails");
eb.ToTable("OrderDetails");
eb.HasKey(e => e.AlternateId);
eb.HasIndex(e => e.Id);
eb.HasOne(e => e.Customer).WithOne();
eb.HasData(
new OrderDetails
{
AlternateId = 1,
Id = -1
});
});
Buna ek olarak, veya HasOne()
Set()
sahip olunan bir tür hedefiyle çağrılması Entity()
artık bir özel durum oluşturur.
Neden?
Bu değişiklik, sahip olunan türün kendisi ile sahip olunan türle ilişki arasında daha temiz bir ayrım oluşturmak için yapılmıştır.
Bu da gibi HasForeignKey
yöntemlerle ilgili belirsizliği ve karışıklığı ortadan kaldırır.
Risk Azaltıcı Etkenler
Yukarıdaki örnekte gösterildiği gibi sahip olunan tür ilişkilerinin yapılandırmasını yeni API yüzeyini kullanacak şekilde değiştirin.
Tabloyu sorumluyla paylaşan bağımlı varlıklar artık isteğe bağlı
Eski davranış
Aşağıdaki modeli ele alalım:
public class Order
{
public int Id { get; set; }
public int CustomerId { get; set; }
public OrderDetails Details { get; set; }
}
public class OrderDetails
{
public int Id { get; set; }
public string ShippingAddress { get; set; }
}
EF Core 3.0'ın öncesinde, aynı tabloya aitse Order
veya açıkça eşlenmişseOrderDetails
, yeni Order
bir eklerken her zaman bir OrderDetails
örnek gerekiyordu.
Yeni davranış
3.0'dan başlayarak EF Core, olmadan OrderDetails
eklemeye Order
olanak tanır ve birincil anahtar dışındaki tüm OrderDetails
özellikleri null atanabilir sütunlara eşler.
EF Core sorgulandığında, gerekli özelliklerinden herhangi birinin değeri yoksa veya birincil anahtar dışında gerekli özellikleri yoksa ve tüm özellikleri ise olarak ayarlanıyor OrderDetails
null
null
.
Risk Azaltıcı Etkenler
Modelinizde tüm isteğe bağlı sütunlara bağımlı bir tablo paylaşımı varsa ancak buna işaret eden gezintinin olması beklenmiyorsa null
, gezinti null
olduğunda uygulamanın durumlarla başa çıkabilecek şekilde değiştirilmesi gerekir. Bu mümkün değilse, varlık türüne gerekli bir özellik eklenmelidir veya en az bir özelliğin kendisine atanmamışnull
bir değeri olmalıdır.
Eşzamanlılık belirteci sütunuyla tablo paylaşan tüm varlıkların bunu bir özelliğe eşlemesi gerekir
Eski davranış
Aşağıdaki modeli ele alalım:
public class Order
{
public int Id { get; set; }
public int CustomerId { get; set; }
public byte[] Version { get; set; }
public OrderDetails Details { get; set; }
}
public class OrderDetails
{
public int Id { get; set; }
public string ShippingAddress { get; set; }
}
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.Entity<Order>()
.Property(o => o.Version).IsRowVersion().HasColumnName("Version");
}
EF Core 3.0'ın öncesinde, aynı tabloya aitse Order
veya açıkça eşlenmişse OrderDetails
güncelleştirme OrderDetails
yalnızca istemcideki değeri güncelleştirmez Version
ve sonraki güncelleştirme başarısız olur.
Yeni davranış
3.0 sürümünden itibaren EF Core, sahipse yeni Version
değeri öğesine Order
yayılımını sağlar OrderDetails
. Aksi takdirde, model doğrulaması sırasında bir özel durum oluşturulur.
Neden?
Bu değişiklik, aynı tabloya eşlenen varlıklardan yalnızca biri güncelleştirildiğinde eski bir eşzamanlılık belirteci değerini önlemek için yapılmıştır.
Risk Azaltıcı Etkenler
Tabloyu paylaşan tüm varlıkların eşzamanlılık belirteci sütununa eşlenmiş bir özellik içermesi gerekir. Gölge durumunda bir tane oluşturmak mümkündür:
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.Entity<OrderDetails>()
.Property<byte[]>("Version").IsRowVersion().HasColumnName("Version");
}
Sahip olunan varlıklar, sahip izleme sorgusu kullanmadan sorgulanamaz
Eski davranış
EF Core 3.0'dan önce, sahip olunan varlıklar başka bir gezinti olarak sorgulanabilir.
context.People.Select(p => p.Address);
Yeni davranış
3.0'dan başlayarak, bir izleme sorgusu sahibi olmayan sahipli bir varlığı projelendiriyorsa EF Core oluşturur.
Neden?
Sahip olunan varlıklar sahip olmadan işlenemez, bu nedenle çoğu durumda bunları bu şekilde sorgulamak bir hatadır.
Risk Azaltıcı Etkenler
Sahip olunan varlığın daha sonra herhangi bir şekilde değiştirilmesi için izlenmesi gerekiyorsa, sahip sorguya dahil edilmelidir.
Aksi takdirde bir AsNoTracking()
çağrı ekleyin:
context.People.Select(p => p.Address).AsNoTracking();
Eşlenmemiş türlerden devralınan özellikler artık tüm türetilmiş türler için tek bir sütuna eşleniyor
Eski davranış
Aşağıdaki modeli ele alalım:
public abstract class EntityBase
{
public int Id { get; set; }
}
public abstract class OrderBase : EntityBase
{
public int ShippingAddress { get; set; }
}
public class BulkOrder : OrderBase
{
}
public class Order : OrderBase
{
}
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.Ignore<OrderBase>();
modelBuilder.Entity<EntityBase>();
modelBuilder.Entity<BulkOrder>();
modelBuilder.Entity<Order>();
}
EF Core 3.0'da özellik varsayılan ShippingAddress
olarak ve Order
için BulkOrder
ayrı sütunlara eşlenir.
Yeni davranış
3.0'dan başlayarak EF Core için ShippingAddress
yalnızca bir sütun oluşturur.
Neden?
Eski davranış beklenmedikti.
Risk Azaltıcı Etkenler
Özelliği yine de türetilen türlerdeki ayrı sütuna açıkça eşlenebilir:
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.Ignore<OrderBase>();
modelBuilder.Entity<EntityBase>();
modelBuilder.Entity<BulkOrder>()
.Property(o => o.ShippingAddress).HasColumnName("BulkShippingAddress");
modelBuilder.Entity<Order>()
.Property(o => o.ShippingAddress).HasColumnName("ShippingAddress");
}
Yabancı anahtar özellik kuralı artık asıl özellik ile aynı adla eşleşir
Eski davranış
Aşağıdaki modeli ele alalım:
public class Customer
{
public int CustomerId { get; set; }
public ICollection<Order> Orders { get; set; }
}
public class Order
{
public int Id { get; set; }
public int CustomerId { get; set; }
}
EF Core 3.0'ın CustomerId
öncesinde, özellik kurala göre yabancı anahtar için kullanılacaktır.
Ancak, sahip olunan bir türse Order
, bu da birincil anahtarı oluşturur CustomerId
ve bu genellikle beklenti değildir.
Yeni davranış
3.0'dan başlayarak EF Core, asıl özellik ile aynı ada sahipse, yabancı anahtarların özelliklerini kurala göre kullanmaya çalışmaz. Asıl özellik adıyla birleştirilmiş asıl tür adı ve asıl özellik adı desenleriyle birleştirilmiş gezinti adı yine eşleştirilir. Örneğin:
public class Customer
{
public int Id { get; set; }
public ICollection<Order> Orders { get; set; }
}
public class Order
{
public int Id { get; set; }
public int CustomerId { get; set; }
}
public class Customer
{
public int Id { get; set; }
public ICollection<Order> Orders { get; set; }
}
public class Order
{
public int Id { get; set; }
public int BuyerId { get; set; }
public Customer Buyer { get; set; }
}
Neden?
Bu değişiklik, sahip olunan türde hatalı bir birincil anahtar özelliğinin tanımlanmasını önlemek için yapılmıştır.
Risk Azaltıcı Etkenler
Özelliğin yabancı anahtar olması ve dolayısıyla birincil anahtarın bir parçası olması amaçlandıysa, bunu açıkça bu şekilde yapılandırın.
TransactionScope tamamlanmadan önce artık kullanılmıyorsa veritabanı bağlantısı kapatılır
Eski davranış
EF Core 3.0'ın öncesinde bağlam bir içinde TransactionScope
bağlantıyı açarsa, geçerli TransactionScope
etkinken bağlantı açık kalır.
using (new TransactionScope())
{
using (AdventureWorks context = new AdventureWorks())
{
context.ProductCategories.Add(new ProductCategory());
context.SaveChanges();
// Old behavior: Connection is still open at this point
var categories = context.ProductCategories().ToList();
}
}
Yeni davranış
3.0'dan başlayarak EF Core, bağlantıyı kullanımı biter bitmez kapatır.
Neden?
Bu değişiklik aynı TransactionScope
içinde birden çok bağlam kullanılmasına olanak tanır. Yeni davranış EF6 ile de eşleşir.
Risk Azaltıcı Etkenler
Bağlantının açık kalması gerekiyorsa, EF Core'un bağlantıyı erken kapatmadığından emin olmak için OpenConnection()
açık çağrı:
using (new TransactionScope())
{
using (AdventureWorks context = new AdventureWorks())
{
context.Database.OpenConnection();
context.ProductCategories.Add(new ProductCategory());
context.SaveChanges();
var categories = context.ProductCategories().ToList();
context.Database.CloseConnection();
}
}
Her özellik bağımsız bellek içi tamsayı anahtar oluşturma kullanır
Eski davranış
EF Core 3.0'den önce, tüm bellek içi tamsayı anahtar özellikleri için bir paylaşılan değer oluşturucu kullanıldı.
Yeni davranış
EF Core 3.0'dan başlayarak, bellek içi veritabanı kullanılırken her tamsayı anahtar özelliği kendi değer oluşturucusunu alır. Ayrıca veritabanı silinirse tüm tablolar için anahtar oluşturma sıfırlanır.
Neden?
Bu değişiklik, bellek içi anahtar oluşturma işlemini gerçek veritabanı anahtarı oluşturma işlemine daha yakından hizalamak ve bellek içi veritabanını kullanırken testleri birbirinden yalıtma özelliğini geliştirmek için yapılmıştır.
Risk Azaltıcı Etkenler
Bu, ayarlanacak belirli bellek içi anahtar değerlerini kullanan bir uygulamayı bozabilir. Bunun yerine belirli anahtar değerlerine güvenmeyin veya yeni davranışla eşleşecek şekilde güncelleştirin.
Yedekleme alanları varsayılan olarak kullanılır
Eski davranış
3.0'ın öncesinde, bir özelliğin yedekleme alanı bilinse bile, EF Core yine de özellik alıcı ve ayarlayıcı yöntemlerini kullanarak özellik değerini varsayılan olarak okur ve yazar. Bunun istisnası sorgu yürütmeydi ve burada yedekleme alanı biliniyorsa doğrudan ayarlanırdı.
Yeni davranış
EF Core 3.0'dan başlayarak, bir özelliğin yedekleme alanı biliniyorsa, EF Core her zaman yedekleme alanını kullanarak bu özelliği okur ve yazar. Bu, uygulama getter veya ayarlayıcı yöntemlerine kodlanmış ek davranışlara güveniyorsa uygulama bozulmasına neden olabilir.
Neden?
Bu değişiklik, EF Core'un varlıkları içeren veritabanı işlemleri gerçekleştirirken iş mantığını varsayılan olarak hatalı bir şekilde tetiklemesini önlemek için yapılmıştır.
Risk Azaltıcı Etkenler
3.0 öncesi davranış, üzerinde ModelBuilder
özellik erişim modunun yapılandırması aracılığıyla geri yüklenebilir.
Örneğin:
modelBuilder.UsePropertyAccessMode(PropertyAccessMode.PreferFieldDuringConstruction);
Birden çok uyumlu yedekleme alanı bulunursa oluşturma
Eski davranış
EF Core 3.0'ın öncesinde, bir özelliğin yedekleme alanını bulma kurallarıyla eşleşen birden çok alan varsa, bazı öncelik sırasına göre bir alan seçilir. Bu, belirsiz durumlarda yanlış alanın kullanılmasına neden olabilir.
Yeni davranış
EF Core 3.0'dan başlayarak, aynı özellik ile birden çok alan eşleştirilirse bir özel durum oluşturulur.
Neden?
Bu değişiklik, yalnızca bir alan doğru olduğunda bir alanın başka bir alan üzerinde sessizce kullanılmasını önlemek için yapılmıştır.
Risk Azaltıcı Etkenler
Belirsiz yedekleme alanları olan özellikler açıkça kullanılacak alana sahip olmalıdır. Örneğin, akıcı API'yi kullanarak:
modelBuilder
.Entity<Blog>()
.Property(e => e.Id)
.HasField("_id");
Yalnızca alan özellik adları alan adıyla eşleşmelidir
Eski davranış
EF Core 3.0'den önce, bir özellik bir dize değeri tarafından belirtilebilirdi ve .NET türünde bu ada sahip bir özellik bulunamazsa EF Core bunu kural kurallarını kullanarak bir alanla eşleştirmeye çalışır.
private class Blog
{
private int _id;
public string Name { get; set; }
}
modelBuilder
.Entity<Blog>()
.Property("Id");
Yeni davranış
EF Core 3.0'dan başlayarak, yalnızca alan özelliğinin alan adıyla tam olarak eşleşmesi gerekir.
modelBuilder
.Entity<Blog>()
.Property("_id");
Neden?
Bu değişiklik, benzer şekilde adlandırılmış iki özellik için aynı alanın kullanılmasını önlemek için yapılmıştır, aynı zamanda yalnızca alan özellikleri için eşleşen kuralları CLR özelliklerine eşlenen özelliklerle aynı hale getirir.
Risk Azaltıcı Etkenler
Yalnızca alan özellikleri, eşlendikleri alanla aynı şekilde adlandırılmalıdır. 3.0'dan sonraki bir EF Core sürümünde, özellik adından farklı bir alan adını açıkça yapılandırmayı yeniden etkinleştirmeyi planlıyoruz (sorun #15307'ye bakın):
modelBuilder
.Entity<Blog>()
.Property("Id")
.HasField("_id");
AddDbContext/AddDbContextPool artık AddLogging ve AddMemoryCache'i çağıramaz
Eski davranış
EF Core 3.0'den önce, addlogging ve AddMemoryCache çağrıları aracılığıyla di ile günlüğe kaydetme ve bellek önbelleğe alma hizmetlerini çağırmak AddDbContext
veya AddDbContextPool
kaydetmek de gerekir.
Yeni davranış
EF Core 3.0'dan AddDbContext
başlayarak bu AddDbContextPool
hizmetleri artık Bağımlılık Ekleme (DI) ile kaydetmeyecektir.
Neden?
EF Core 3.0, bu hizmetlerin uygulamanın DI kapsayıcısında olmasını gerektirmez. Ancak uygulamanın DI kapsayıcısında kayıtlıysa ILoggerFactory
EF Core tarafından kullanılmaya devam eder.
Risk Azaltıcı Etkenler
Uygulamanızın bu hizmetlere ihtiyacı varsa, AddLogging veya AddMemoryCache kullanarak bunları açıkça DI kapsayıcısıyla kaydedin.
AddEntityFramework* boyut sınırıyla IMemoryCache ekler
Eski davranış
EF Core 3.0'da çağrı AddEntityFramework*
yöntemleri, bellek önbelleğe alma hizmetlerini boyut sınırı olmadan DI ile de kaydeder.
Yeni davranış
EF Core 3.0'dan başlayarak, AddEntityFramework*
boyut sınırı olan bir IMemoryCache hizmetini kaydeder. Daha sonra eklenen diğer hizmetler IMemoryCache'e bağımlıysa, özel durumlara veya performansın düşmesine neden olan varsayılan sınıra hızla ulaşabilirler.
Neden?
IMemoryCache'in sınır olmadan kullanılması, sorgu önbelleğe alma mantığında bir hata varsa veya sorgular dinamik olarak oluşturulursa denetimsiz bellek kullanımına neden olabilir. Varsayılan sınıra sahip olmak olası bir DoS saldırısını azaltır.
Risk Azaltıcı Etkenler
Çoğu durumda da çağrılırsa veya AddDbContextPool
çağrılırsa AddDbContext
çağrı AddEntityFramework*
yapılması gerekmez. Bu nedenle, en iyi azaltma çağrıyı AddEntityFramework*
kaldırmaktır.
Uygulamanızın bu hizmetlere ihtiyacı varsa, AddMemoryCache kullanarak önceden DI kapsayıcısıyla açıkça bir IMemoryCache uygulaması kaydedin.
DbContext.Entry artık yerel detectchanges gerçekleştiriyor
Eski davranış
EF Core 3.0'ın çağrılması DbContext.Entry
, izlenen tüm varlıklar için değişikliklerin algılanmasına neden olabilir.
Bu, içinde EntityEntry
kullanıma sunulan durumun güncel olmasını sağlar.
Yeni davranış
EF Core 3.0'dan başlayarak, çağrı DbContext.Entry
artık yalnızca belirli varlıktaki değişiklikleri ve bununla ilgili izlenen sorumlu varlıkları algılamayı deneyecek.
Bu, başka bir yerde yapılan değişikliklerin bu yöntem çağrılarak algılanmayabileceği ve bunun uygulama durumu üzerinde etkileri olabileceği anlamına gelir.
Olarak ayarlanırsa ChangeTracker.AutoDetectChangesEnabled
false
, bu yerel değişiklik algılamanın bile devre dışı bırakılacağını unutmayın.
Değişiklik algılamaya neden olan diğer yöntemler (örneğin ChangeTracker.Entries
ve SaveChanges
) yine de izlenen tüm varlıkların dolu DetectChanges
olmasına neden olur.
Neden?
Bu değişiklik, kullanarak context.Entry
varsayılan performansını geliştirmek için yapılmıştır.
Risk Azaltıcı Etkenler
3.0 öncesi davranışından emin olmak için aramadan Entry
önce açıkça çağırınChangeTracker.DetectChanges()
.
Dize ve bayt dizisi anahtarları varsayılan olarak istemci tarafından oluşturulmaz
Eski davranış
EF Core 3.0'ın string
öncesinde ve byte[]
anahtar özellikleri açıkça null olmayan bir değer ayarlanmadan kullanılabilir.
Böyle bir durumda, anahtar değeri istemcide GUID olarak oluşturulur ve için byte[]
bayt olarak seri hale getirilir.
Yeni davranış
EF Core 3.0'dan başlayarak hiçbir anahtar değerinin ayarlanmadığını belirten bir özel durum oluşturulur.
Neden?
Bu değişiklik, istemci tarafından oluşturulan string
/byte[]
değerlerin genel olarak yararlı olmadığından ve varsayılan davranış, oluşturulan anahtar değerlerin ortak bir şekilde akılda olmasını zorlaştırdığından yapıldı.
Risk Azaltıcı Etkenler
3.0 öncesi davranış, anahtar özelliklerinin null olmayan başka bir değer ayarlanmamışsa oluşturulan değerleri kullanması gerektiğini açıkça belirterek elde edilebilir. Örneğin, akıcı API ile:
modelBuilder
.Entity<Blog>()
.Property(e => e.Id)
.ValueGeneratedOnAdd();
Veya veri ek açıklamaları ile:
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public string Id { get; set; }
ILoggerFactory artık kapsamlı bir hizmettir
Eski davranış
EF Core 3.0'ın ILoggerFactory
öncesinde tekil hizmet olarak kaydedilmişti.
Yeni davranış
EF Core 3.0'dan itibaren kapsamı ILoggerFactory
belirlenmiş olarak kaydedilir.
Neden?
Bu değişiklik, bir günlükçünün bir DbContext
örnekle ilişkilendirilip başka işlevlere olanak tanıyan ve iç hizmet sağlayıcılarının patlaması gibi bazı patolojik davranış durumlarını ortadan kaldıran bir değişiklik yapıldı.
Risk Azaltıcı Etkenler
Bu değişiklik, EF Core iç hizmet sağlayıcısında özel hizmetler kaydedip kullanmıyorsa uygulama kodunu etkilememelidir.
Bu durum sık görülmez.
Bu gibi durumlarda, çoğu şey çalışmaya devam eder, ancak bağlı ILoggerFactory
olan tüm tekil hizmetin farklı bir şekilde elde ILoggerFactory
edilmesi için değiştirilmesi gerekir.
Bunun gibi durumlarla karşılaşırsanız, gelecekte bunu nasıl tekrar bozmayacağımızı daha iyi anlamamız için ILoggerFactory
ef core github sorun izleyicisinde bir sorun oluşturun.
Yavaş yüklenen proxy'ler artık gezinti özelliklerinin tamamen yüklendiğini varsayma
Eski davranış
EF Core 3.0'dan önce, a DbContext
atıldıktan sonra, bu bağlamdan alınan bir varlıkta belirli bir gezinti özelliğinin tam olarak yüklenip yüklenmediğini bilmenin hiçbir yolu yoktu.
Proxy'ler bunun yerine, null olmayan bir değere sahipse başvuru gezintisi yüklendiğini ve boş değilse koleksiyon gezintisi yüklendiğini varsayar.
Bu gibi durumlarda, yavaş yüklemeye çalışmak bir operasyon dışı olacaktır.
Yeni davranış
EF Core 3.0'dan başlayarak proxy'ler bir gezinti özelliğinin yüklenip yüklenmediğini izler. Bu, bağlam atıldıktan sonra yüklenen bir gezinti özelliğine erişme girişiminin, yüklenen gezinti boş veya null olsa bile her zaman işlem yapılmadığı anlamına gelir. Buna karşılık, yüklenmeyen bir gezinti özelliğine erişmeye çalışmak, gezinti özelliği boş olmayan bir koleksiyon olsa bile bağlam atılırsa bir özel durum oluşturur. Bu durum ortaya çıkarsa, uygulama kodunun geçersiz bir zamanda gecikmeli yüklemeyi kullanmaya çalıştığı ve uygulamanın bunu yapmaması için değiştirilmesi gerektiği anlamına gelir.
Neden?
Bu değişiklik, atılan DbContext
bir örneğe yavaş yüklenmeye çalışılırken davranışı tutarlı ve doğru hale getirmek için yapılmıştır.
Risk Azaltıcı Etkenler
Uygulama kodunu atılan bir bağlamla gecikmeli yüklemeyi denememek için güncelleştirin veya özel durum iletisinde açıklandığı gibi işlem yapılmaması için yapılandırın.
İç hizmet sağlayıcılarının aşırı oluşturulması artık varsayılan olarak bir hatadır
Eski davranış
EF Core 3.0'dan önce, patolojik sayıda iç hizmet sağlayıcısı oluşturan bir uygulama için bir uyarı günlüğe kaydedilir.
Yeni davranış
EF Core 3.0'dan başlayarak, bu uyarı artık dikkate alınır ve hata ve özel durum oluşturulur.
Neden?
Bu değişiklik, bu patolojik durum daha açık bir şekilde ortaya konularak daha iyi uygulama kodu sağlamak için yapılmıştır.
Risk Azaltıcı Etkenler
Bu hatayla karşılaşmanın en uygun nedeni, kök nedeni anlamak ve bu kadar çok iç hizmet sağlayıcısı oluşturmayı durdurmaktır.
Ancak, hata üzerindeki yapılandırma aracılığıyla bir uyarıya geri dönüştürülebilir (veya yoksayılabilir).DbContextOptionsBuilder
Örneğin:
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
optionsBuilder
.ConfigureWarnings(w => w.Log(CoreEventId.ManyServiceProvidersCreatedWarning));
}
HasOne/HasMany için tek bir dizeyle çağrılan yeni davranış
Eski davranış
EF Core 3.0'ın öncesinde, kod çağrısı HasOne
veya HasMany
tek bir dize ile kafa karıştırıcı bir şekilde yorumlandı.
Örneğin:
modelBuilder.Entity<Samurai>().HasOne("Entrance").WithOne();
Kod, özel olabilecek gezinti özelliğini kullanan başka bir varlık türüyle Entrance
ilgili Samurai
gibi görünüyor.
Gerçekte bu kod, gezinti özelliği olmadan adlı Entrance
bir varlık türüyle ilişki oluşturmayı dener.
Yeni davranış
EF Core 3.0'dan başlayarak yukarıdaki kod artık daha önce olması gerektiği gibi görünüyor.
Neden?
Özellikle yapılandırma kodunu okurken ve hata ararken eski davranış çok kafa karıştırıcıydı.
Risk Azaltıcı Etkenler
Bu, yalnızca tür adları için dizeleri kullanarak ve gezinti özelliğini açıkça belirtmeden ilişkileri açıkça yapılandıran uygulamaları bozar.
Bu yaygın bir durum değildir.
Önceki davranış, gezinti özelliği adı için açıkça geçirerek null
elde edilebilir.
Örneğin:
modelBuilder.Entity<Samurai>().HasOne("Some.Entity.Type.Name", null).WithOne();
Birkaç zaman uyumsuz yöntemin dönüş türü Görev olan ValueTask olarak değiştirildi
Eski davranış
Aşağıdaki zaman uyumsuz yöntemler daha önce bir Task<T>
döndürdü:
DbContext.FindAsync()
DbSet.FindAsync()
DbContext.AddAsync()
DbSet.AddAsync()
ValueGenerator.NextValueAsync()
(ve türetilen sınıflar)
Yeni davranış
Yukarıda belirtilen yöntemler artık öncekiyle aynı T
şekilde bir ValueTask<T>
döndürür.
Neden?
Bu değişiklik, bu yöntemler çağrılırken tahakkuk eden yığın ayırmalarının sayısını azaltarak genel performansı artırır.
Risk Azaltıcı Etkenler
Yalnızca yukarıdaki API'leri bekleyen uygulamaların yeniden derlenmesi gerekir; kaynak değişikliği gerekmez.
Daha karmaşık bir kullanım (örneğin, döndürülenin Task
geçirilmesiTask.WhenAny()
) genellikle döndürülenin ValueTask<T>
üzerinde çağrılarak AsTask()
bir'e Task<T>
dönüştürülmesini gerektirir.
Bunun, bu değişikliğin getirdiği ayırma azaltmasını yok ettiğini unutmayın.
relational:TypeMapping ek açıklaması artık yalnızca TypeMapping
Eski davranış
Tür eşleme ek açıklamalarının ek açıklama adı "relational:TypeMapping" idi.
Yeni davranış
Tür eşleme ek açıklamalarının ek açıklama adı artık "TypeMapping" olur.
Neden?
Tür eşlemeleri artık ilişkisel veritabanı sağlayıcılarından daha fazlası için kullanılıyor.
Risk Azaltıcı Etkenler
Bu, yalnızca tür eşlemesine doğrudan ek açıklama olarak erişen uygulamaları bozar ve bu yaygın değildir. Düzeltilmesi gereken en uygun eylem, ek açıklamayı doğrudan kullanmak yerine tür eşlemelerine erişmek için API yüzeyini kullanmaktır.
Türetilmiş bir türdeki ToTable özel durum oluşturur
Eski davranış
Ef Core 3.0'dan önce türetilmiş ToTable()
bir türe çağrılan, yalnızca devralma eşleme stratejisinin geçerli olmadığı TPH olduğu için yoksayılır.
Yeni davranış
EF Core 3.0'dan başlayarak ve türetilmiş bir tür üzerinde çağrılan TPT ve TPC desteğini sonraki bir sürüme ToTable()
ekleme hazırlığında, gelecekte beklenmeyen bir eşleme değişikliğini önlemek için bir özel durum oluşturacaktır.
Neden?
Şu anda türetilmiş bir türü farklı bir tabloyla eşlemek geçerli değildir. Bu değişiklik, yapılacak geçerli bir şey haline geldiğinde gelecekte kırılmayı önler.
Risk Azaltıcı Etkenler
Türetilmiş türleri diğer tablolarla eşleme girişimlerini kaldırın.
ForSqlServerHasIndex, HasIndex ile değiştirildi
Eski davranış
EF Core 3.0'ın öncesinde ile ForSqlServerHasIndex().ForSqlServerInclude()
INCLUDE
kullanılan sütunları yapılandırmanın bir yolu sağlandı.
Yeni davranış
EF Core 3.0'dan başlayarak, dizinde kullanmak Include
artık ilişkisel düzeyde desteklenmektedir.
HasIndex().ForSqlServerInclude()
adresini kullanın.
Neden?
Bu değişiklik, dizinler Include
için API'yi tüm veritabanı sağlayıcıları için tek bir yerde birleştirmek için yapılmıştır.
Risk Azaltıcı Etkenler
Yukarıda gösterildiği gibi yeni API'yi kullanın.
Meta veri API'sinde yapılan değişiklikler
Yeni davranış
Aşağıdaki özellikler uzantı yöntemlerine dönüştürüldü:
IEntityType.QueryFilter
->GetQueryFilter()
IEntityType.DefiningQuery
->GetDefiningQuery()
IProperty.IsShadowProperty
->IsShadowProperty()
IProperty.BeforeSaveBehavior
->GetBeforeSaveBehavior()
IProperty.AfterSaveBehavior
->GetAfterSaveBehavior()
Neden?
Bu değişiklik, yukarıda belirtilen arabirimlerin uygulanmasını basitleştirir.
Risk Azaltıcı Etkenler
Yeni uzantı yöntemlerini kullanın.
Sağlayıcıya özgü Meta Veri API'sinde yapılan değişiklikler
Yeni davranış
Sağlayıcıya özgü uzantı yöntemleri düzleştirilmiş olacaktır:
IProperty.Relational().ColumnName
->IProperty.GetColumnName()
IEntityType.SqlServer().IsMemoryOptimized
->IEntityType.IsMemoryOptimized()
PropertyBuilder.UseSqlServerIdentityColumn()
->PropertyBuilder.UseIdentityColumn()
Neden?
Bu değişiklik, yukarıda belirtilen uzantı yöntemlerinin uygulanmasını basitleştirir.
Risk Azaltıcı Etkenler
Yeni uzantı yöntemlerini kullanın.
EF Core artık SQLite FK zorlaması için pragma göndermez
Eski davranış
EF Core 3.0'a başlamadan önce EF Core, SQLite bağlantısı açıldığında gönderir PRAGMA foreign_keys = 1
.
Yeni davranış
EF Core 3.0'dan başlayarak, SQLite bağlantısı açıldığında EF Core artık göndermez PRAGMA foreign_keys = 1
.
Neden?
Bu değişiklik, EF Core'un varsayılan olarak kullandığından SQLitePCLRaw.bundle_e_sqlite3
yapılmıştır; bu da FK zorlamanın varsayılan olarak açık olduğu ve her bağlantı açıldığında açıkça etkinleştirilmesi gerekmeyen bir durumdur.
Risk Azaltıcı Etkenler
Yabancı anahtarlar, EF Core için varsayılan olarak kullanılan SQLitePCLRaw.bundle_e_sqlite3 varsayılan olarak etkinleştirilir.
Diğer durumlarda, yabancı anahtarlar bağlantı dizesi belirtilerek Foreign Keys=True
etkinleştirilebilir.
Microsoft.EntityFrameworkCore.Sqlite artık SQLitePCLRaw.bundle_e_sqlite3
Eski davranış
EF Core 3.0'da EF Core kullanılır.SQLitePCLRaw.bundle_green
Yeni davranış
EF Core 3.0'dan başlayarak EF Core kullanır SQLitePCLRaw.bundle_e_sqlite3
.
Neden?
Bu değişiklik, iOS'ta kullanılan SQLite sürümünün diğer platformlarla tutarlı olması için yapılmıştır.
Risk Azaltıcı Etkenler
iOS'ta yerel SQLite sürümünü kullanmak için farklı SQLitePCLRaw
bir paket kullanacak şekilde yapılandırınMicrosoft.Data.Sqlite
.
Guid değerleri artık SQLite üzerinde METNEÇEVİr olarak depolanıyor
Eski davranış
Guid değerleri daha önce SQLite'te BLOB değerleri olarak depolanıyordu.
Yeni davranış
Guid değerleri artık METNEÇEVİr olarak depolanır.
Neden?
Guid'lerin ikili biçimi standartlaştırılmaz. Değerleri METNEÇEVİr olarak depolamak veritabanını diğer teknolojilerle daha uyumlu hale getirir.
Risk Azaltıcı Etkenler
Sql'i aşağıdaki gibi yürüterek mevcut veritabanlarını yeni biçime geçirebilirsiniz.
UPDATE MyTable
SET GuidColumn = hex(substr(GuidColumn, 4, 1)) ||
hex(substr(GuidColumn, 3, 1)) ||
hex(substr(GuidColumn, 2, 1)) ||
hex(substr(GuidColumn, 1, 1)) || '-' ||
hex(substr(GuidColumn, 6, 1)) ||
hex(substr(GuidColumn, 5, 1)) || '-' ||
hex(substr(GuidColumn, 8, 1)) ||
hex(substr(GuidColumn, 7, 1)) || '-' ||
hex(substr(GuidColumn, 9, 2)) || '-' ||
hex(substr(GuidColumn, 11, 6))
WHERE typeof(GuidColumn) == 'blob';
EF Core'da, bu özelliklerde bir değer dönüştürücü yapılandırarak önceki davranışı kullanmaya devam edebilirsiniz.
modelBuilder
.Entity<MyEntity>()
.Property(e => e.GuidProperty)
.HasConversion(
g => g.ToByteArray(),
b => new Guid(b));
Microsoft.Data.Sqlite hem BLOB hem de METNEÇEVİr sütunlarından Guid değerlerini okuyabilme özelliğine sahiptir; ancak, parametreler ve sabitler için varsayılan biçim değiştiğinden Guid'ler içeren çoğu senaryo için eylem gerçekleştirmeniz gerekebilir.
Char değerleri artık SQLite üzerinde METNEÇEVİr olarak depolanır
Eski davranış
Char değerleri daha önce SQLite'te INTEGER değerleri olarak depolanıyordu. Örneğin, A karakter değeri 65 tamsayı değeri olarak depolandı.
Yeni davranış
Char değerleri artık METNEÇEVİr olarak depolanır.
Neden?
Değerleri METNEÇEVİr olarak depolamak daha doğaldır ve veritabanını diğer teknolojilerle daha uyumlu hale getirir.
Risk Azaltıcı Etkenler
Sql'i aşağıdaki gibi yürüterek mevcut veritabanlarını yeni biçime geçirebilirsiniz.
UPDATE MyTable
SET CharColumn = char(CharColumn)
WHERE typeof(CharColumn) = 'integer';
EF Core'da, bu özelliklerde bir değer dönüştürücü yapılandırarak önceki davranışı kullanmaya devam edebilirsiniz.
modelBuilder
.Entity<MyEntity>()
.Property(e => e.CharProperty)
.HasConversion(
c => (long)c,
i => (char)i);
Microsoft.Data.Sqlite aynı zamanda tamsayı ve METNEÇEVİr sütunlarından karakter değerlerini okuyabilme özelliğine de sahiptir, bu nedenle bazı senaryolar herhangi bir eylem gerektirmeyebilir.
Geçiş kimlikleri artık sabit kültürün takvimi kullanılarak oluşturulur
Eski davranış
Geçiş kimlikleri, geçerli kültürün takvimi kullanılarak yanlışlıkla oluşturulmuştur.
Yeni davranış
Geçiş kimlikleri artık her zaman sabit kültürün takvimi (Gregoryen) kullanılarak oluşturulur.
Neden?
Veritabanını güncelleştirirken veya birleştirme çakışmalarını çözerken geçişlerin sırası önemlidir. Sabit takvimin kullanılması, ekip üyelerinin farklı sistem takvimlerine sahip olmasından kaynaklanabilir sıralama sorunlarını önler.
Risk Azaltıcı Etkenler
Bu değişiklik, yılın Gregoryen takvimden (Tay Budist takvimi gibi) daha büyük olduğu Gregoryen olmayan bir takvim kullanan herkesi etkiler. Mevcut geçiş kimliklerinin güncelleştirilmesi gerekir; böylece yeni geçişler mevcut geçişlerden sonra sıralanır.
Geçiş kimliği, geçişlerin tasarımcı dosyalarındaki Migration özniteliğinde bulunabilir.
[DbContext(typeof(MyDbContext))]
-[Migration("25620318122820_MyMigration")]
+[Migration("20190318122820_MyMigration")]
partial class MyMigration
{
Geçiş geçmişi tablosunun da güncelleştirilmesi gerekir.
UPDATE __EFMigrationsHistory
SET MigrationId = CONCAT(LEFT(MigrationId, 4) - 543, SUBSTRING(MigrationId, 4, 150))
UseRowNumberForPaging kaldırıldı
Eski davranış
EF Core 3.0'ın öncesinde, UseRowNumberForPaging
SQL Server 2008 ile uyumlu disk belleği için SQL oluşturmak için kullanılabilir.
Yeni davranış
EF Core 3.0'dan başlayarak, EF yalnızca sonraki SQL Server sürümleriyle uyumlu olan disk belleği için SQL oluşturur.
Neden?
SQL Server 2008 artık desteklenen bir ürün olmadığından ve EF Core 3.0'da yapılan sorgu değişiklikleriyle çalışmak için bu özelliği güncelleştirmek önemli bir iş olduğundan bu değişikliği yapıyoruz.
Risk Azaltıcı Etkenler
Oluşturulan SQL'in desteklenmesi için SQL Server'ın daha yeni bir sürümüne güncelleştirmenizi veya daha yüksek bir uyumluluk düzeyi kullanmanızı öneririz. Bununla birlikte, bunu yapamıyorsanız, lütfen ayrıntılarla izleme sorunu hakkında yorum yapın. Geri bildirime dayanarak bu kararı yeniden ziyaret edebiliriz.
Uzantı bilgileri/meta verileri IDbContextOptionsExtension'dan kaldırıldı
Eski davranış
IDbContextOptionsExtension
uzantı hakkında meta veriler sağlamak için kapsanan yöntemler.
Yeni davranış
Bu yöntemler, yeni bir özellikten döndürülen yeni DbContextOptionsExtensionInfo
bir IDbContextOptionsExtension.Info
soyut temel sınıfa taşınmıştır.
Neden?
2.0 ile 3.0 sürümleri üzerinde bu yöntemleri birkaç kez eklememiz veya değiştirmemiz gerekiyordu. Bunları yeni bir soyut temel sınıfa ayırmak, mevcut uzantıları bozmadan bu tür değişiklikler yapmayı kolaylaştırır.
Risk Azaltıcı Etkenler
Uzantıları yeni deseni izleyecek şekilde güncelleştirin.
EF Core kaynak kodundaki farklı uzantı türleri için birçok uygulamasında IDbContextOptionsExtension
örnekler bulunur.
LogQueryPossibleExceptionWithAggregateOperator yeniden adlandırıldı
Değiştir
RelationalEventId.LogQueryPossibleExceptionWithAggregateOperator
olarak yeniden adlandırıldı RelationalEventId.LogQueryPossibleExceptionWithAggregateOperatorWarning
.
Neden?
Bu uyarı olayının adlandırmasını diğer tüm uyarı olaylarıyla hizalar.
Risk Azaltıcı Etkenler
Yeni adı kullanın. (Olay kimliği numarasının değişmediğini unutmayın.)
Yabancı anahtar kısıtlama adları için API'sini netleştirme
Eski davranış
EF Core 3.0'da yabancı anahtar kısıtlama adları yalnızca "ad" olarak adlandırıldı. Örneğin:
var constraintName = myForeignKey.Name;
Yeni davranış
EF Core 3.0'dan başlayarak yabancı anahtar kısıtlama adları artık "kısıtlama adı" olarak adlandırılır. Örneğin:
var constraintName = myForeignKey.ConstraintName;
Neden?
Bu değişiklik, bu alandaki adlandırmaya tutarlılık getirir ve bunun yabancı anahtarın tanımlandığı sütun veya özellik adı değil, yabancı anahtar kısıtlamasının adı olduğunu da açıklar.
Risk Azaltıcı Etkenler
Yeni adı kullanın.
IRelationalDatabaseCreator.HasTables/HasTablesAsync genel kullanıma açık hale getirildi
Eski davranış
EF Core 3.0'da bu yöntemler korunuyordu.
Yeni davranış
EF Core 3.0'dan başlayarak bu yöntemler geneldir.
Neden?
Bu yöntemler EF tarafından bir veritabanının oluşturulup oluşturulmadığını ancak boş olup olmadığını belirlemek için kullanılır. Bu, geçişlerin uygulanıp uygulanmayacağını belirlerken EF dışından da yararlı olabilir.
Risk Azaltıcı Etkenler
Geçersiz kılmaların erişilebilirliğini değiştirin.
Microsoft.EntityFrameworkCore.Design artık bir DevelopmentDependency paketidir
Eski davranış
EF Core 3.0'da Microsoft.EntityFrameworkCore.Design, derlemesine bağımlı projeler tarafından başvurulabilen normal bir NuGet paketiydi.
Yeni davranış
EF Core 3.0'dan başlayarak bir DevelopmentDependency paketidir. Bu, bağımlılığın diğer projelere geçişli olarak akmayacağı ve artık varsayılan olarak derlemesine başvurmayacağınız anlamına gelir.
Neden?
Bu paket yalnızca tasarım zamanında kullanılmak üzere tasarlanmıştır. Dağıtılan uygulamalar buna başvurmamalıdır. Paketin DevelopmentDependency olması bu öneriyi güçlendirir.
Risk Azaltıcı Etkenler
EF Core'un tasarım zamanı davranışını geçersiz kılmak için bu pakete başvurmanız gerekiyorsa, projenizdeki PackageReference öğesi meta verilerini güncelleştirebilirsiniz.
<PackageReference Include="Microsoft.EntityFrameworkCore.Design" Version="3.0.0">
<PrivateAssets>all</PrivateAssets>
<!-- Remove IncludeAssets to allow compiling against the assembly -->
<!--<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>-->
</PackageReference>
Pakete Microsoft.EntityFrameworkCore.Tools aracılığıyla geçişli olarak başvuru yapılıyorsa, meta verilerini değiştirmek için pakete açık bir PackageReference eklemeniz gerekir. Böyle açık bir başvuru, paketten türlerin gerekli olduğu herhangi bir projeye eklenmelidir.
SQLitePCL.raw sürüm 2.0.0'a güncelleştirildi
Eski davranış
Microsoft.EntityFrameworkCore.Sqlite daha önce SQLitePCL.raw 1.1.12 sürümüne bağımlıdır.
Yeni davranış
Paketimizi 2.0.0 sürümüne bağlı olarak güncelleştirdik.
Neden?
SQLitePCL.raw sürüm 2.0.0, .NET Standard 2.0'a hedeflemektedir. Daha önce geçişli paketlerin çalışması için büyük bir kapanış gerektiren .NET Standard 1.1'i hedeflemişti.
Risk Azaltıcı Etkenler
SQLitePCL.raw sürüm 2.0.0 bazı hataya neden olan değişiklikleri içerir. Ayrıntılar için sürüm notlarına bakın.
NetTopologySuite 2.0.0 sürümüne güncelleştirildi
Eski davranış
Uzamsal paketler daha önce NetTopologySuite'ın 1.15.1 sürümüne bağımlıdır.
Yeni davranış
Paketimizi sürüm 2.0.0'a bağlı olarak güncelleştirdik.
Neden?
NetTopologySuite sürüm 2.0.0, EF Core kullanıcılarının karşılaştığı çeşitli kullanılabilirlik sorunlarını çözmeyi amaçlar.
Risk Azaltıcı Etkenler
NetTopologySuite sürüm 2.0.0 bazı hataya neden olan değişiklikleri içerir. Ayrıntılar için sürüm notlarına bakın.
System.Data.SqlClient yerine Microsoft.Data.SqlClient kullanılır
Eski davranış
Microsoft.EntityFrameworkCore.SqlServer daha önce System.Data.SqlClient'a bağımlıdır.
Yeni davranış
Paketimizi Microsoft.Data.SqlClient'a bağlı olarak güncelleştirdik.
Neden?
Microsoft.Data.SqlClient, SQL Server'ın ileriye dönük en önemli veri erişim sürücüsüdür ve System.Data.SqlClient artık geliştirmenin odak noktası değildir. Always Encrypted gibi bazı önemli özellikler yalnızca Microsoft.Data.SqlClient üzerinde kullanılabilir.
Risk Azaltıcı Etkenler
Kodunuz System.Data.SqlClient'a doğrudan bağımlılık alıyorsa, bunu bunun yerine Microsoft.Data.SqlClient'a başvuracak şekilde değiştirmeniz gerekir; İki paket çok yüksek düzeyde API uyumluluğunu koruduğundan, bu yalnızca basit bir paket ve ad alanı değişikliği olmalıdır.
Birden çok belirsiz kendi kendine başvuran ilişki yapılandırılmalıdır
Eski davranış
Birden çok kendi kendine başvuran tek yönlü gezinti özelliklerine ve eşleşen FK'lere sahip bir varlık türü yanlış bir şekilde tek bir ilişki olarak yapılandırıldı. Örneğin:
public class User
{
public Guid Id { get; set; }
public User CreatedBy { get; set; }
public User UpdatedBy { get; set; }
public Guid CreatedById { get; set; }
public Guid? UpdatedById { get; set; }
}
Yeni davranış
Bu senaryo artık model oluşturmada algılanır ve modelin belirsiz olduğunu belirten bir özel durum oluşturulur.
Neden?
Sonuçta elde edilen model belirsizdi ve büyük olasılıkla bu durum için yanlış olacaktır.
Risk Azaltıcı Etkenler
İlişkinin tam yapılandırmasını kullanın. Örneğin:
modelBuilder
.Entity<User>()
.HasOne(e => e.CreatedBy)
.WithMany();
modelBuilder
.Entity<User>()
.HasOne(e => e.UpdatedBy)
.WithMany();
DbFunction.Schema'nın null veya boş dize olması, modelin varsayılan şemasında olacak şekilde yapılandırıyor
Eski davranış
Boş bir dize olarak şema ile yapılandırılmış bir DbFunction, şemasız yerleşik işlev olarak ele alınıyordu. Örneğin aşağıdaki kod CLR işlevini SqlServer'daki yerleşik işlevle DATEPART
eşlerDatePart
.
[DbFunction("DATEPART", Schema = "")]
public static int? DatePart(string datePartArg, DateTime? date) => throw new Exception();
Yeni davranış
Tüm DbFunction eşlemelerinin kullanıcı tanımlı işlevlerle eşlendiği kabul edilir. Bu nedenle boş dize değeri işlevi modelin varsayılan şemasının içine koyar. Bu, akıcı API modelBuilder.HasDefaultSchema()
aracılığıyla veya dbo
başka bir şekilde açıkça yapılandırılan şema olabilir.
Neden?
Daha önce şemanın boş olması, bu işlevin yerleşik olduğunu işlemenin bir yoluydu, ancak bu mantık yalnızca yerleşik işlevlerin herhangi bir şemaya ait olmadığı SqlServer için geçerlidir.
Risk Azaltıcı Etkenler
DbFunction'ın çevirisini yerleşik bir işlevle eşlemek için el ile yapılandırın.
modelBuilder
.HasDbFunction(typeof(MyContext).GetMethod(nameof(MyContext.DatePart)))
.HasTranslation(args => SqlFunctionExpression.Create("DatePart", args, typeof(int?), null));
EF Core 3.0, .NET Standard 2.0 Geri Döndürülür yerine .NET Standard 2.1'i hedefler
EF Core 3.0, .NET Framework uygulamalarını dışlayan hataya neden olan .NET Standard 2.1'i hedefler. EF Core 3.1 bunu geri döndürerek .NET Standard 2.0'ı yeniden hedeflemektedir.
Sorgu yürütme hata ayıklama düzeyinde günlüğe kaydedilir Geri Döndürüldü
EF Core 3.0'daki yeni yapılandırma, herhangi bir olayın uygulama tarafından belirtilmesine izin verdiğinden bu değişikliği geri aldık. Örneğin, SQL günlüğünü olarak değiştirmek için Debug
veya AddDbContext
içindeki OnConfiguring
düzeyi açıkça yapılandırın:
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
=> optionsBuilder
.UseSqlServer(connectionString)
.ConfigureWarnings(c => c.Log((RelationalEventId.CommandExecuting, LogLevel.Debug)));