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.
Bir yönün birden çok varlık türünde aynı şekilde yapılandırılması gerektiğinde, aşağıdaki teknikler kod yinelemesini azaltmaya ve mantığı birleştirmeye olanak sağlar.
Aşağıda sunulan kod parçacıklarını içeren tam örnek projeye bakın.
OnModelCreating'de toplu yapılandırma
öğesinden ModelBuilder döndürülen her oluşturucu nesnesi, modeli oluşturan nesnelere alt düzey erişim sağlayan bir Model veya Metadata özelliğini kullanıma sunar. Özellikle, modeldeki belirli nesneler üzerinde yineleme yapmanızı ve bunlara ortak yapılandırma uygulamanızı sağlayan yöntemler vardır.
Aşağıdaki örnekte model özel bir değer türü Currencyiçerir:
public readonly struct Currency
{
public Currency(decimal amount)
=> Amount = amount;
public decimal Amount { get; }
public override string ToString()
=> $"${Amount}";
}
Geçerli EF sağlayıcısı bunu bir veritabanı türüyle eşlemeyi bilmediğinden, bu türün özellikleri varsayılan olarak bulunmaz. Bu kod parçacığı, OnModelCreating türünün tüm özelliklerini ekler ve desteklenen bir türe bir değer dönüştürücüsü yapılandırır - Currency:
foreach (var entityType in modelBuilder.Model.GetEntityTypes())
{
foreach (var propertyInfo in entityType.ClrType.GetProperties())
{
if (propertyInfo.PropertyType == typeof(Currency))
{
entityType.AddProperty(propertyInfo)
.SetValueConverter(typeof(CurrencyConverter));
}
}
}
public class CurrencyConverter : ValueConverter<Currency, decimal>
{
public CurrencyConverter()
: base(
v => v.Amount,
v => new Currency(v))
{
}
}
Meta Veri API'sinin dezavantajları
-
Fluent API'sinin aksine modelde yapılan her değişikliğin açıkça yapılması gerekir. Örneğin, bazı
Currencyözellikler bir kural tarafından gezinti olarak yapılandırıldıysa, bir varlık türü özelliği eklemeden önce CLR özelliğine başvuran gezintiyi kaldırmanız gerekir. #9117 bunu geliştirecektir. - Kurallar her değişiklik sonrasında çalışır. Eğer bir konvansiyon tarafından bulunan bir gezintiyi kaldırırsanız, konvansiyon tekrar çalışır ve bunu geri ekleyebilir. Bunun olmasını önlemek için, ya DelayConventions() çağırarak özelliğin eklenmesine kadar sözleşmeleri geciktirip ardından döndürülen nesneyi yok etmeniz ya da AddIgnored kullanarak CLR özelliğini yoksayıldı olarak işaretlemeniz gerekir.
- Bu yineleme gerçekleştirildikten sonra varlık türleri eklenebilir ve yapılandırma bunlara uygulanmaz. Bu durum genellikle bu kodu sonuna
OnModelCreatingyerleştirerek önlenebilir, ancak birbirine bağlı iki yapılandırma kümeniz varsa, bunların tutarlı bir şekilde uygulanmasına izin verecek bir sıra olmayabilir.
Kongre öncesi yapılandırma
EF Core, belirli bir CLR türü için eşleme yapılandırmasının bir kez belirtilmesine izin verir; bu yapılandırma daha sonra modelde bulunan bu türdeki tüm özelliklere uygulanır. Model oluşturma kurallarının çalışmasına izin verilmeden önce modelin yönlerini yapılandırdığından buna "kural öncesi model yapılandırması" denir. Bu tür yapılandırma, ConfigureConventions türünden türetilen tipte DbContext öğesiyle geçersiz kılınarak uygulanır.
Bu örnekte, türün Currency tüm özelliklerinin bir değer dönüştürücüsü olacak şekilde nasıl yapılandırılır gösterilmektedir:
protected override void ConfigureConventions(ModelConfigurationBuilder configurationBuilder)
{
configurationBuilder
.Properties<Currency>()
.HaveConversion<CurrencyConverter>();
}
Ve bu örnek, string türündeki tüm özelliklerin bazı yönlerinin nasıl yapılandırıldığını göstermektedir:
configurationBuilder
.Properties<string>()
.AreUnicode(false)
.HaveMaxLength(1024);
Uyarı
çağrısında ConfigureConventions belirtilen tür bir temel tür, arabirim veya genel tür tanımı olabilir. Tüm eşleşen yapılandırmalar, en az ayrıntılı olandan başlayarak sırayla uygulanacaktır.
- Arayüz
- Temel tür
- Genel tür tanımı
- Boş değeri kabul etmeyen değer türü
- Kesin tür
Önemli
Kural öncesi yapılandırma, modele eşleşen bir nesne eklendiğinde uygulanan açık yapılandırmaya eşdeğerdir. Tüm kuralları ve Veri Ek Açıklamalarını geçersiz kılar. Örneğin, yukarıdaki yapılandırmayla tüm dize yabancı anahtar özellikleri, asıl anahtarla MaxLength eşleşmese bile 1024 ile unicode olmayan olarak oluşturulur.
Türleri yoksayma
Önceden yapılandırma ayrıca bir türü gözardı etmeye ve onun bir varlık türü veya varlık türünde bir özellik olarak kurallarca keşfedilmesini önler.
configurationBuilder
.IgnoreAny(typeof(IList<>));
Varsayılan tür eşlemesi
Genel olarak, bu tür bir özellik için bir değer dönüştürücü belirttiğiniz sürece EF, sağlayıcı tarafından desteklenmeyen bir türdeki sabitlere sahip sorguları çevirebilir. Ancak, bu tür özellikleri içermeyen sorgularda EF'nin doğru değer dönüştürücüsünün bulunmasına imkan yoktur. Bu durumda, DefaultTypeMapping arayarak sağlayıcı türü eşlemesi eklemek veya geçersiz kılmak mümkündür.
configurationBuilder
.DefaultTypeMapping<Currency>()
.HasConversion<CurrencyConverter>();
Kongre öncesi yapılandırma sınırlamaları
- Bu yaklaşımla birçok özellik yapılandırılamaz. #6787 bunu daha fazla türe genişletir.
- Şu anda yapılandırma yalnızca CLR türü tarafından belirlenir. #20418 özel koşula izin verir.
- Bu yapılandırma, bir model oluşturulmadan önce gerçekleştirilir. Uygulanırken ortaya çıkan çakışmalar varsa, istisna yığını izlemesinde
ConfigureConventionsyöntemi yer almayabilir, bu nedenle sebebini bulmak daha zor olabilir.
Konvansiyonlar
EF Core model oluşturma kuralları, model oluşturulurken modelde yapılan değişikliklere göre tetiklenen mantığı içeren sınıflardır. Bu, açık yapılandırma yapıldıkçe, eşleme öznitelikleri uygulandığında ve diğer kurallar çalıştırıldığında modelin -date up-totutar. Buna katılmak için her kural, ilgili yöntemin ne zaman tetikleneceğini belirleyen bir veya daha fazla arabirim uygular. Örneğin, modele yeni bir varlık türü eklendiğinde uygulayan IEntityTypeAddedConvention bir kural tetiklenir. Benzer şekilde, hem IForeignKeyAddedConvention hem de IKeyAddedConvention'i uygulayan bir sözleşme, modele bir anahtar veya yabancı anahtar eklendiğinde tetiklenecektir.
Model oluşturma kuralları, model yapılandırmasını denetlemenin güçlü bir yoludur, ancak karmaşık ve düzeltilmesi zor olabilir. Çoğu durumda, özellikler ve türler için ortak yapılandırmayı kolayca belirtmek için kural öncesi model yapılandırması kullanılabilir.
Yeni kural ekleme
Örnek: Ayrımcı özelliklerin uzunluğunu kısıtla
Hiyerarşi başına tablo devralma eşleme stratejisi, belirli bir satırda hangi türün gösterileceğini belirtmek için ayrıştırıcı sütun gerektirir. Varsayılan olarak, EF, herhangi bir diskriminatör uzunluğu için çalışmasını sağlayan sınırsız bir dize sütunu kullanır. Ancak, ayrımcı dizelerin uzunluk üst sınırının kısıtlanması, depolama ve sorguların daha verimli olmasını sağlayabilir. Şimdi bunu yapacak yeni bir kural oluşturalım.
EF Core model oluşturma kuralları, model oluşturulurken modelde yapılan değişikliklere bağlı olarak tetiklenir. Bu, açık yapılandırma yapıldıkçe, eşleme öznitelikleri uygulandığında ve diğer kurallar çalıştırıldığında modelin -date up-totutar. Buna katılmak için her kural, kuralın ne zaman tetikleneceğini belirleyen bir veya daha fazla arabirim uygular. Örneğin, modele yeni bir varlık türü eklendiğinde uygulayan IEntityTypeAddedConvention bir kural tetiklenir. Benzer şekilde, hem IForeignKeyAddedConvention hem de IKeyAddedConvention'i uygulayan bir sözleşme, modele bir anahtar veya yabancı anahtar eklendiğinde tetiklenecektir.
Modele bir noktada yapılan yapılandırma daha sonraki bir noktada değiştirilebileceği veya kaldırılabildiği için uygulanacak arabirimleri bilmek karmaşık olabilir. Örneğin, bir anahtar varsayımla oluşturulabilir, ancak daha sonra farklı bir anahtar açıkça yapılandırıldığında değiştirilebilir.
Ayırıcı uzunluk kuralını uygulamaya yönelik ilk denemeyi yaparak bunu biraz daha somut hale getirelim:
public class DiscriminatorLengthConvention1 : IEntityTypeBaseTypeChangedConvention
{
public void ProcessEntityTypeBaseTypeChanged(
IConventionEntityTypeBuilder entityTypeBuilder,
IConventionEntityType? newBaseType,
IConventionEntityType? oldBaseType,
IConventionContext<IConventionEntityType> context)
{
var discriminatorProperty = entityTypeBuilder.Metadata.FindDiscriminatorProperty();
if (discriminatorProperty != null
&& discriminatorProperty.ClrType == typeof(string))
{
discriminatorProperty.Builder.HasMaxLength(24);
}
}
}
Bu kural, IEntityTypeBaseTypeChangedConvention öğesini uygular, bu da bir varlık türü için eşlenmiş devralma hiyerarşisi her değiştirildiğinde tetikleneceği anlamına gelir. Konvansiyon daha sonra hiyerarşi için dize ayrıştırıcısı özelliğini bulur ve yapılandırır.
Bu kural daha sonra Add içinde ConfigureConventions çağrılarak kullanılır.
protected override void ConfigureConventions(ModelConfigurationBuilder configurationBuilder)
{
configurationBuilder.Conventions.Add(_ => new DiscriminatorLengthConvention1());
}
Uyarı
Add yöntemi, kuralın örneklerini doğrudan eklemek yerine kuralın örneklerini oluşturacak bir fabrikayı alır. Bu, kuralın EF Core iç hizmet sağlayıcısından bağımlılıkları kullanmasına olanak tanır. Bu kuralın bağımlılıkları olmadığından, hizmet sağlayıcısı parametresi hiçbir zaman kullanılmadığını belirten olarak adlandırılır _.
Modeli oluşturmak ve varlık türüne Post bakmak, bunun işe yaradığını gösterir; ayırıcı özelliği artık en fazla 24 uzunlukla yapılandırılır:
Discriminator (no field, string) Shadow Required AfterSave:Throw MaxLength(24)
Ancak şimdi açıkça farklı bir ayrımcı özelliği yapılandırırsak ne olur? Örneğin:
modelBuilder.Entity<Post>()
.HasDiscriminator<string>("PostTypeDiscriminator")
.HasValue<Post>("Post")
.HasValue<FeaturedPost>("Featured");
Modelin hata ayıklama görünümüne baktığımızda, ayrıştırıcı uzunluğunun artık yapılandırılmadığını tespit ediyoruz.
PostTypeDiscriminator (no field, string) Shadow Required AfterSave:Throw
Bunun nedeni, kuralımızda yapılandırdığımız ayırıcı özelliğinin daha sonra özel ayrıştırıcı eklendiğinde kaldırılmış olmasıdır. Ayrıştırıcı değişikliklere tepki vermek için kuralımızda başka bir arabirim uygulayarak bunu düzeltmeye çalışabiliriz, ancak hangi arabirimi uygulayacağımızı bulmak kolay değildir.
Neyse ki daha kolay bir yaklaşım var. Çoğu zaman, son model doğru olduğu sürece modelin oluşturulurken nasıl göründüğü önemli değildir. Buna ek olarak, uygulamak istediğimiz yapılandırmanın genellikle tepki vermek için başka kuralları tetiklemesi gerekmez. Bu nedenle, kuralımız IModelFinalizingConvention uygulayabilir.
Model sonlandırma kuralları , diğer tüm model oluşturma işlemleri tamamlandıktan sonra çalıştırılır ve bu nedenle modelin neredeyse son durumuna erişebilirsiniz. Bu, her model değişikliğine tepki veren etkileşimli kuralların aksinedir ve yöntemi yürütmenin herhangi bir noktasında OnModelCreating modelin up-to-date olduğundan emin olun. Model bitirme uzlaşısı genellikle tüm modele tekrar tekrar işlem yaparak, model öğelerini yapılandırır. Bu durumda modeldeki tüm ayrımcıları bulup yapılandıracağız:
public class DiscriminatorLengthConvention2 : IModelFinalizingConvention
{
public void ProcessModelFinalizing(IConventionModelBuilder modelBuilder, IConventionContext<IConventionModelBuilder> context)
{
foreach (var entityType in modelBuilder.Metadata.GetEntityTypes()
.Where(entityType => entityType.BaseType == null))
{
var discriminatorProperty = entityType.FindDiscriminatorProperty();
if (discriminatorProperty != null
&& discriminatorProperty.ClrType == typeof(string))
{
discriminatorProperty.Builder.HasMaxLength(24);
}
}
}
}
Modeli bu yeni kuralla derledikten sonra, ayrıştırıcı uzunluğunun özelleştirildiği halde doğru yapılandırıldığını fark ettik:
PostTypeDiscriminator (no field, string) Shadow Required AfterSave:Throw MaxLength(24)
Bir adım ileri gidebilir ve maksimum uzunluğu en uzun ayırıcı değerin uzunluğu olacak şekilde yapılandırabiliriz:
public class DiscriminatorLengthConvention3 : IModelFinalizingConvention
{
public void ProcessModelFinalizing(IConventionModelBuilder modelBuilder, IConventionContext<IConventionModelBuilder> context)
{
foreach (var entityType in modelBuilder.Metadata.GetEntityTypes()
.Where(entityType => entityType.BaseType == null))
{
var discriminatorProperty = entityType.FindDiscriminatorProperty();
if (discriminatorProperty != null
&& discriminatorProperty.ClrType == typeof(string))
{
var maxDiscriminatorValueLength =
entityType.GetDerivedTypesInclusive().Select(e => ((string)e.GetDiscriminatorValue()!).Length).Max();
discriminatorProperty.Builder.HasMaxLength(maxDiscriminatorValueLength);
}
}
}
}
Artık en uzun ayırıcı sütun uzunluğu 8'dir ve bu da kullanımdaki en uzun ayrıştırıcı değeri olan "Öne Çıkan" uzunluğudur.
PostTypeDiscriminator (no field, string) Shadow Required AfterSave:Throw MaxLength(8)
Örnek: Tüm dize özellikleri için varsayılan uzunluk
Bir sonlandırma kuralının kullanılabildiği başka bir örneğe bakalım: Herhangi bir dize özelliği için varsayılan maksimum uzunluk ayarlama. Kural önceki örneğe oldukça benzer:
public class MaxStringLengthConvention : IModelFinalizingConvention
{
public void ProcessModelFinalizing(IConventionModelBuilder modelBuilder, IConventionContext<IConventionModelBuilder> context)
{
foreach (var property in modelBuilder.Metadata.GetEntityTypes()
.SelectMany(
entityType => entityType.GetDeclaredProperties()
.Where(
property => property.ClrType == typeof(string))))
{
property.Builder.HasMaxLength(512);
}
}
}
Bu kural oldukça basittir. Modeldeki her dize özelliğini bulur ve maksimum uzunluğunu 512 olarak ayarlar. özelliklerinde Posthata ayıklama görünümüne baktığımızda, tüm dize özelliklerinin artık en fazla 512 uzunluğuna sahip olduğunu görüyoruz.
EntityType: Post
Properties:
Id (int) Required PK AfterSave:Throw ValueGenerated.OnAdd
AuthorId (no field, int?) Shadow FK Index
BlogId (no field, int) Shadow Required FK Index
Content (string) Required MaxLength(512)
Discriminator (no field, string) Shadow Required AfterSave:Throw MaxLength(512)
PublishedOn (DateTime) Required
Title (string) Required MaxLength(512)
Uyarı
Aynı işlem, kural öncesi yapılandırmayla da gerçekleştirilebilir, ancak kural kullanılması, geçerli özelliklerin daha fazla filtrelenmesine ve Veri Ek Açıklamalarının yapılandırmayı geçersiz kılmasına olanak tanır.
Son olarak, bu örnekten ayrılmadan önce hem MaxStringLengthConvention hem de DiscriminatorLengthConvention3'i aynı anda kullanırsak ne olur? Bunun yanıtı, model sonlandırma kuralları eklendikleri sırayla çalıştırıldığından, bunların hangi sırayla eklendiğine bağlıdır. Bu nedenle, en son eklenirse MaxStringLengthConvention , en son çalışır ve ayırıcı özelliğinin maksimum uzunluğunu 512 olarak ayarlar. Bu nedenle, bu durumda, diğer tüm dize özelliklerini 512 olarak bırakırken, yalnızca ayırt edici özellikler için varsayılan maksimum uzunluğu geçersiz kılmak amacıyla en son DiscriminatorLengthConvention3 eklemek daha iyidir.
Mevcut bir kuralı değiştirme
Bazen mevcut bir kuralı tamamen kaldırmak yerine temelde aynı şeyi ancak değişen davranışı olan bir kuralla değiştirmek istiyoruz. Mevcut kural zaten uygun şekilde tetiklenmesi gereken arabirimleri uygulayacağından bu yararlı olur.
Örnek: Özellik haritalandırmayı seçme
EF Core, tüm genel okuma-yazma özelliklerini kurala göre eşler. Bu, varlık türlerinizin tanımlanma biçimi için uygun olmayabilir. Bunu değiştirmek için, PropertyDiscoveryConvention ile açıkça eşlenmediği veya yeni bir öznitelik olan OnModelCreating ile işaretlenmediği sürece Persist öğesini herhangi bir özelliği eşlemeyen kendi uygulamamızla değiştirilebiliriz.
[AttributeUsage(AttributeTargets.Property | AttributeTargets.Field)]
public sealed class PersistAttribute : Attribute
{
}
Yeni kural şu şekildedir:
public class AttributeBasedPropertyDiscoveryConvention : PropertyDiscoveryConvention
{
public AttributeBasedPropertyDiscoveryConvention(ProviderConventionSetBuilderDependencies dependencies)
: base(dependencies)
{
}
public override void ProcessEntityTypeAdded(
IConventionEntityTypeBuilder entityTypeBuilder,
IConventionContext<IConventionEntityTypeBuilder> context)
=> Process(entityTypeBuilder);
public override void ProcessEntityTypeBaseTypeChanged(
IConventionEntityTypeBuilder entityTypeBuilder,
IConventionEntityType? newBaseType,
IConventionEntityType? oldBaseType,
IConventionContext<IConventionEntityType> context)
{
if ((newBaseType == null
|| oldBaseType != null)
&& entityTypeBuilder.Metadata.BaseType == newBaseType)
{
Process(entityTypeBuilder);
}
}
private void Process(IConventionEntityTypeBuilder entityTypeBuilder)
{
foreach (var memberInfo in GetRuntimeMembers())
{
if (Attribute.IsDefined(memberInfo, typeof(PersistAttribute), inherit: true))
{
entityTypeBuilder.Property(memberInfo);
}
else if (memberInfo is PropertyInfo propertyInfo
&& Dependencies.TypeMappingSource.FindMapping(propertyInfo) != null)
{
entityTypeBuilder.Ignore(propertyInfo.Name);
}
}
IEnumerable<MemberInfo> GetRuntimeMembers()
{
var clrType = entityTypeBuilder.Metadata.ClrType;
foreach (var property in clrType.GetRuntimeProperties()
.Where(p => p.GetMethod != null && !p.GetMethod.IsStatic))
{
yield return property;
}
foreach (var property in clrType.GetRuntimeFields())
{
yield return property;
}
}
}
}
Tavsiye
Yerleşik bir kuralı değiştirirken, yeni kural uygulaması mevcut kural sınıfından devralmalıdır. Bazı kuralların ilişkisel veya sağlayıcıya özgü uygulamaları olduğunu unutmayın. Bu durumda, yeni kural uygulaması kullanımdaki veritabanı sağlayıcısı için en belirli mevcut kural sınıfından devralmalıdır.
Kural daha sonra Replace yöntemi kullanılarak ConfigureConventions içinde kaydedilir:
protected override void ConfigureConventions(ModelConfigurationBuilder configurationBuilder)
{
configurationBuilder.Conventions.Replace<PropertyDiscoveryConvention>(
serviceProvider => new AttributeBasedPropertyDiscoveryConvention(
serviceProvider.GetRequiredService<ProviderConventionSetBuilderDependencies>()));
}
Tavsiye
Bu durum, mevcut kuralın bağımlılık nesnesiyle ProviderConventionSetBuilderDependencies temsil edilen bağımlılıklara sahip olduğu bir durumdur. Bunlar kullanılarak GetRequiredService iç hizmet sağlayıcısından alınır ve kural oluşturucusuna geçirilir.
Bu kuralın, ile [Persist]işaretlendikleri sürece alanların eşlenmesine (özelliklere ek olarak) izin verdiğine dikkat edin. Bu, özel alanları modelde gizli anahtarlar olarak kullanabileceğimiz anlamına gelir.
Örneğin, aşağıdaki varlık türlerini göz önünde bulundurun:
public class LaundryBasket
{
[Persist]
[Key]
private readonly int _id;
[Persist]
public int TenantId { get; init; }
public bool IsClean { get; set; }
public List<Garment> Garments { get; } = new();
}
public class Garment
{
public Garment(string name, string color)
{
Name = name;
Color = color;
}
[Persist]
[Key]
private readonly int _id;
[Persist]
public int TenantId { get; init; }
[Persist]
public string Name { get; }
[Persist]
public string Color { get; }
public bool IsClean { get; set; }
public LaundryBasket? Basket { get; set; }
}
Bu varlık türlerinden oluşturulan model:
Model:
EntityType: Garment
Properties:
_id (_id, int) Required PK AfterSave:Throw ValueGenerated.OnAdd
Basket_id (no field, int?) Shadow FK Index
Color (string) Required
Name (string) Required
TenantId (int) Required
Navigations:
Basket (LaundryBasket) ToPrincipal LaundryBasket Inverse: Garments
Keys:
_id PK
Foreign keys:
Garment {'Basket_id'} -> LaundryBasket {'_id'} ToDependent: Garments ToPrincipal: Basket ClientSetNull
Indexes:
Basket_id
EntityType: LaundryBasket
Properties:
_id (_id, int) Required PK AfterSave:Throw ValueGenerated.OnAdd
TenantId (int) Required
Navigations:
Garments (List<Garment>) Collection ToDependent Garment Inverse: Basket
Keys:
_id PK
Normalde IsClean eşlenirdi, ancak [Persist] ile işaretlenmediğinden, artık eşlenmemiş bir özellik olarak değerlendirilir.
Tavsiye
Özellik eşlendikten sonra daha fazla yapılandırılması için çalıştırılması gereken mevcut model sonlandırma sözleşmeleri olduğundan, bu sözleşme model sonlandırma sözleşmesi olarak uygulanamadı.
Kurallar uygulamasıyla ilgili dikkat edilmesi gerekenler
EF Core, her yapılandırma parçasının nasıl yapıldığını izler. Bu, ConfigurationSource numaralandırma tarafından temsil edilir. Farklı yapılandırma türleri şunlardır:
-
Explicit: Model öğesi açıkça içinde yapılandırıldıOnModelCreating -
DataAnnotation: Model öğesi CLR türünde eşleme özniteliği (veri ek açıklaması) kullanılarak yapılandırıldı -
Convention: Model öğesi bir model oluşturma kuralı tarafından yapılandırıldı
Kurallar, DataAnnotation veya Explicit olarak işaretlenmiş yapılandırmayı hiçbir zaman geçersiz kılmamalıdır. Bu, bir kural oluşturucu kullanılarak, özelliğinden elde edilen IConventionPropertyBuilder, örneğin Builder kullanılarak elde edilir. Örneğin:
property.Builder.HasMaxLength(512);
HasMaxLength üzerinde kural oluşturucusunu çağırmak, yalnızca bir eşleme özniteliğiyle veya OnModelCreating içinde önceden yapılandırılmadıysa maksimum uzunluğu ayarlar.
Bunun gibi oluşturucu yöntemlerinin ikinci bir parametresi de vardır: fromDataAnnotation. Kural bir eşleme özniteliği adına yapılandırma yapıyorsa bunu true olarak ayarlayın. Örneğin:
property.Builder.HasMaxLength(512, fromDataAnnotation: true);
Bu, ConfigurationSource değerini DataAnnotation olarak ayarlar. Bu, değerin artık OnModelCreating üzerinde açık eşleme yoluyla geçersiz kılınabileceği, ancak eşleme dışı öznitelik kuralları tarafından geçersiz kılınamayacağı anlamına gelir.
Geçerli yapılandırma geçersiz kılınamazsa, yöntem null döndürür; bu durumda, daha fazla yapılandırma gerçekleştirmeniz gerekiyorsa bunu göz önünde bulundurmalısınız.
property.Builder.HasMaxLength(512)?.IsUnicode(false);
Unicode yapılandırması geçersiz kılınamazsa bile, en fazla uzunluk yine de ayarlanacaktır. Yüzeyleri yalnızca her iki çağrı da başarılı olduğunda yapılandırmanız gerektiğinde, bunu önceden kontrol etmek için CanSetMaxLength ve CanSetIsUnicode çağrılarını yaparak inceleyebilirsiniz.
public class MaxStringLengthNonUnicodeConvention : IModelFinalizingConvention
{
public void ProcessModelFinalizing(IConventionModelBuilder modelBuilder, IConventionContext<IConventionModelBuilder> context)
{
foreach (var property in modelBuilder.Metadata.GetEntityTypes()
.SelectMany(
entityType => entityType.GetDeclaredProperties()
.Where(
property => property.ClrType == typeof(string))))
{
var propertyBuilder = property.Builder;
if (propertyBuilder.CanSetMaxLength(512)
&& propertyBuilder.CanSetIsUnicode(false))
{
propertyBuilder.HasMaxLength(512)!.IsUnicode(false);
}
}
}
}
Burada, HasMaxLength çağrısının null döndürmeyeceğinden emin olabiliriz.
HasMaxLength ile farklı olabileceğinden, propertyBuilder ile döndürülen oluşturucu örneğinin kullanılması yine de önerilir.
Uyarı
Diğer kurallar, bir kural değişiklik yaptıktan hemen sonra tetiklenmez, tüm kurallar geçerli değişikliği işlemeyi bitirene kadar geciktirilir.
IConventionContext
Tüm kural yöntemlerinin de bir IConventionContext<TMetadata> parametresi vardır. Bazı durumlarda yararlı olabilecek yöntemler sağlar.
Örnek: NotMappedAttribute kuralı
Bu konvansiyon, modele eklenen bir türde NotMappedAttribute arar ve bu varlık türünü modelden kaldırmaya çalışır. Ancak varlık türü modelden kaldırılırsa, uygulanan ProcessEntityTypeAdded diğer kuralların artık çalıştırılması gerekmez. Bu, StopProcessing() çağrılarak gerçekleştirilebilir.
public virtual void ProcessEntityTypeAdded(
IConventionEntityTypeBuilder entityTypeBuilder,
IConventionContext<IConventionEntityTypeBuilder> context)
{
var type = entityTypeBuilder.Metadata.ClrType;
if (!Attribute.IsDefined(type, typeof(NotMappedAttribute), inherit: true))
{
return;
}
if (entityTypeBuilder.ModelBuilder.Ignore(entityTypeBuilder.Metadata.Name, fromDataAnnotation: true) != null)
{
context.StopProcessing();
}
}
IConventionModel
Kurala geçirilen her oluşturucu nesnesi, modeli oluşturan nesnelere alt düzey erişim sağlayan bir Metadata özelliği kullanıma sunar. Özellikle, modeldeki belirli nesneler üzerinde yineleme yapmanıza ve bunlara Örnek: Tüm dize özellikleri için varsayılan uzunluk bölümünde görüldüğü gibi ortak yapılandırma uygulamanıza olanak sağlayan yöntemler vardır. Bu API, IMutableModelToplu yapılandırma kısmında gösterilene benzer.
Dikkat
Oluşturucular verilen yapılandırmanın Fluent API veya Veri Ek Açıklamaları kullanılarak önceden belirtilmiş bir şeyi geçersiz kılıp geçersiz kılmayacağını denetlediğinden, her zaman özellik olarak Builder kullanıma sunulan oluşturucuda yöntemleri çağırarak yapılandırma gerçekleştirmeniz tavsiye edilir.
Toplu yapılandırma için her yaklaşımın ne zaman kullanılacağı
Meta Veri API'lerini şu durumlarda kullanın:
- Yapılandırmanın belirli bir zamanda uygulanması ve modeldeki sonraki değişikliklere tepki vermemesi gerekir.
- Model oluşturma hızı çok önemlidir. Meta veri API'sinde daha az güvenlik denetimi vardır ve bu nedenle diğer yaklaşımlara göre biraz daha hızlı olabilir, ancak Derlenmiş modelin kullanılması daha da iyi başlangıç süreleri getirir.
Aşağıdaki durumlarda Kural öncesi model yapılandırmasını kullanın:
- Uygulanabilirlik koşulu yalnızca türüne bağlı olduğundan basittir.
- Belirtilen türden bir özellik modele eklendiğinde yapılandırmanın uygulanması gerekir ve bu, Veri Ek Açıklamaları ile kuralları geçersiz kılar.
Aşağıdaki durumlarda Sonlandırma Kurallarını kullanın:
- Uygulanabilirlik koşulu karmaşıktır.
- Yapılandırma, Veri Ek Açıklamaları tarafından belirtilenleri geçersiz kılmamalıdır.
Aşağıdaki durumlarda Etkileşimli Kuralları kullanın:
- Birden çok kural birbirine bağlıdır. Son haline getirme kuralları eklendikleri sırayla çalışır ve bu nedenle kuralları daha sonra sonlandırarak yapılan değişikliklere tepki veremez.
- Mantık çeşitli bağlamlar arasında paylaşılır. Etkileşimli kurallar diğer yaklaşımlardan daha güvenlidir.