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.
Not
EF4.1 Yalnızca Devamı - Bu sayfada ele alınan özellikler, API'ler vb. Entity Framework 4.1'de sunulmuştur. Önceki bir sürümü kullanıyorsanız, bu bilgilerin bazıları veya tümü geçerli değildir.
Bu sayfadaki içerik, Julie Lerman (<http://thedatafarm.com> ) tarafından yazılan bir makaleden uyarlanmıştır.
Entity Framework Code First, EF'in sorgulama, değişiklik izleme ve güncelleştirme işlevlerini gerçekleştirmek için kullandığı modeli temsil etmek için kendi etki alanı sınıflarınızı kullanmanıza olanak tanır. Code First, 'yapılandırma üzerinde kural' olarak adlandırılan bir programlama düzeninden yararlanır. Code First, sınıflarınızın Entity Framework kurallarına uygun olduğunu varsayar ve bu durumda işinin nasıl gerçekleştirileceğine otomatik olarak çalışır. Ancak, sınıflarınız bu kurallara uymuyorsa, EF'ye gerekli bilgileri sağlamak için sınıflarınıza yapılandırmalar ekleyebilirsiniz.
Code First, bu yapılandırmaları sınıflarınıza eklemek için size iki yol sağlar. Bunlardan biri DataAnnotations adlı basit öznitelikleri, ikincisi ise kodda yapılandırmaları kesin olarak açıklamanızı sağlayan Code First Fluent API'sini kullanmaktır.
Bu makale, sınıflarınızı yapılandırmak için DataAnnotations (System.ComponentModel.DataAnnotations ad alanında) kullanımına odaklanacak ve en sık gereken yapılandırmaları vurgulayacaktır. DataAnnotations, bu uygulamaların istemci tarafı doğrulamaları için aynı ek açıklamalardan yararlanmasını sağlayan ASP.NET MVC gibi bir dizi .NET uygulaması tarafından da anlaşılır.
Model
Basit bir sınıf çifti ile Code First DataAnnotations'ı göstereceğim: Blog ve Gönderi.
public class Blog
{
public int Id { get; set; }
public string Title { get; set; }
public string BloggerName { get; set;}
public virtual ICollection<Post> Posts { get; set; }
}
public class Post
{
public int Id { get; set; }
public string Title { get; set; }
public DateTime DateCreated { get; set; }
public string Content { get; set; }
public int BlogId { get; set; }
public ICollection<Comment> Comments { get; set; }
}
Oldukları gibi, Blog ve Post sınıfları kod ilk kuralını rahatça izler ve EF uyumluluğunu etkinleştirmek için herhangi bir ayarlama gerektirmez. Ancak ek açıklamaları kullanarak EF'e sınıflar ve bunların eşlendiği veritabanı hakkında daha fazla bilgi sağlayabilirsiniz.
Anahtar
Entity Framework, her varlığın varlık izleme için kullanılan bir anahtar değerine sahip olmasına dayanır. Code First kuralından biri örtük anahtar özellikleridir; Code First, "Id" adlı bir özelliği veya "BlogId" gibi sınıf adı ve "Kimlik" birleşimini arar. Bu özellik veritabanındaki birincil anahtar sütununa eşlenir.
Blog ve Post sınıflarının her ikisi de bu kuralı izler. Ya yapmasalardı? Blog bunun yerine PrimaryTrackingKey veya hatta foo adını kullandıysa ne olur? Kod önce bu kuralla eşleşen bir özellik bulamazsa, Entity Framework'ün bir anahtar özelliğine sahip olmanız gerektiği gereksinimi nedeniyle bir özel durum oluşturur. EntityKey olarak hangi özelliğin kullanılacağını belirtmek için anahtar ek açıklamasını kullanabilirsiniz.
public class Blog
{
[Key]
public int PrimaryTrackingKey { get; set; }
public string Title { get; set; }
public string BloggerName { get; set;}
public virtual ICollection<Post> Posts { get; set; }
}
Kod öncesinin veritabanı oluşturma özelliğini kullanıyorsanız, Blog tablosunda primaryTrackingKey adlı birincil anahtar sütunu bulunur ve bu sütun varsayılan olarak Kimlik olarak da tanımlanır.
Bileşik anahtarlar
Entity Framework, birden fazla özellikten oluşan birincil anahtarlar olan bileşik anahtarları destekler. Örneğin, birincil anahtarı PassportNumber ve IssuingCountry'nin birleşimi olan bir Passport sınıfınız olabilir.
public class Passport
{
[Key]
public int PassportNumber { get; set; }
[Key]
public string IssuingCountry { get; set; }
public DateTime Issued { get; set; }
public DateTime Expires { get; set; }
}
EF modelinizde yukarıdaki sınıfı kullanmayı denemeniz bir InvalidOperationExceptionile sonuçlanır:
'Passport' türü için bileşik birincil anahtar sıralaması belirlenemiyor. Bileşik birincil anahtarlar için bir sıra belirtmek üzere ColumnAttribute veya HasKey yöntemini kullanın.
Bileşik anahtarları kullanmak için Entity Framework, anahtar özellikleri için bir sıra tanımlamanızı gerektirir. Bunu yapmak için Sütun açıklamasını kullanarak bir sıralama belirtebilirsiniz.
Not
Sıra değeri görelidir (dizin tabanlı değil). Bu nedenle tüm değerler kullanılabilir. Örneğin, 1 ve 2 yerine 100 ve 200 kabul edilebilir.
public class Passport
{
[Key]
[Column(Order=1)]
public int PassportNumber { get; set; }
[Key]
[Column(Order = 2)]
public string IssuingCountry { get; set; }
public DateTime Issued { get; set; }
public DateTime Expires { get; set; }
}
Bileşik yabancı anahtarlara sahip varlıklarınız varsa, ilgili birincil anahtar özellikleri için kullandığınız sütun sıralamasını belirtmeniz gerekir.
Yalnızca yabancı anahtar özelliklerindeki göreli sıralamanın aynı olması gerekir; Order'a atanan değerlerin tam olarak eşleşmesi gerekmez. Örneğin, aşağıdaki sınıfta 1 ve 2 yerine 3 ve 4 kullanılabilir.
public class PassportStamp
{
[Key]
public int StampId { get; set; }
public DateTime Stamped { get; set; }
public string StampingCountry { get; set; }
[ForeignKey("Passport")]
[Column(Order = 1)]
public int PassportNumber { get; set; }
[ForeignKey("Passport")]
[Column(Order = 2)]
public string IssuingCountry { get; set; }
public Passport Passport { get; set; }
}
Zorunlu
Ek açıklama EF'ye Required belirli bir özelliğin gerekli olduğunu bildirir.
Title özelliğine Gerekli ifadesinin eklenmesi, EF (ve MVC) tarafından özelliğin bir değer içermesini zorunlu kılar.
[Required]
public string Title { get; set; }
Uygulamada ek kod veya işaretleme değişikliği olmadığında, MVC uygulaması özellik ve ek açıklama adlarını kullanarak dinamik olarak bir ileti oluşturarak bile istemci tarafı doğrulaması gerçekleştirir.
Gerekli özniteliği, eşlenen özelliği null atanamaz hale getirerek oluşturulan veritabanını da etkiler. Başlık alanının "null değil" olarak değiştiğine dikkat edin.
Not
Bazı durumlarda, özellik gerekli olsa bile veritabanındaki sütunun null atanamaz olması mümkün olmayabilir. Örneğin, birden çok tür için TPH devralma stratejisi verileri kullanılırken tek bir tabloda depolanır. Türetilmiş bir tür gerekli bir özellik içeriyorsa, hiyerarşideki tüm türler bu özelliğe sahip olmadığından sütun null atanamaz hale getirilemez.
MaxLength ve MinLength
MaxLength ve MinLength öznitelikleri, aynı ile Requiredyaptığınız gibi ek özellik doğrulamaları belirtmenize olanak sağlar.
Burada, uzunluk gereksinimleri olan BloggerName yer alır. Örnekte özniteliklerin nasıl birleştirildiği de gösterilmektedir.
[MaxLength(10),MinLength(5)]
public string BloggerName { get; set; }
MaxLength ek açıklaması, özelliğin uzunluğunu 10 olarak ayarlayarak veritabanını etkiler.
MVC istemci tarafı ek açıklaması ve EF 4.1 sunucu tarafı ek açıklaması, yine dinamik olarak bir hata iletisi oluşturarak bu doğrulamayı kabul edecektir: "BloggerName alanı en fazla '10' uzunluğunda bir dize veya dizi türü olmalıdır." Bu mesaj biraz uzun. Birçok ek açıklama, ErrorMessage özniteliğiyle bir hata iletisi belirtmenize olanak sağlar.
[MaxLength(10, ErrorMessage="BloggerName must be 10 characters or less"),MinLength(5)]
public string BloggerName { get; set; }
Required anotasyonunda ErrorMessage'i de belirtebilirsiniz.
Eşlenmemiş
Code First kuralı, desteklenen bir veri türündeki her özelliğin veritabanında yer almasını gerektirir. Ancak uygulamalarınızda her zaman böyle bir durum söz konusu değildir. Örneğin, Blog sınıfında Title ve BloggerName alanlarını temel alan bir kod oluşturan bir özelliğiniz olabilir. Bu özellik dinamik olarak oluşturulabilir ve depolanması gerekmez. Bu BlogCode özelliği gibi, veritabanına eşlenmeyen tüm özellikleri NotMapped ek açıklamasıyla işaretleyebilirsiniz.
[NotMapped]
public string BlogCode
{
get
{
return Title.Substring(0, 1) + ":" + BloggerName.Substring(0, 1);
}
}
ComplexType
Bir sınıf kümesinde etki alanı varlıklarınızı açıklamak ve ardından tam bir varlığı açıklamak için bu sınıfları katmana almak sık karşılaşılan bir durum değildir. Örneğin, modelinize BlogDetails adlı bir sınıf ekleyebilirsiniz.
public class BlogDetails
{
public DateTime? DateCreated { get; set; }
[MaxLength(250)]
public string Description { get; set; }
}
BlogDetails Herhangi bir anahtar özelliği türüne sahip olmadığını fark edin. Etki alanı temelli tasarımda değer BlogDetails nesnesi olarak adlandırılır. Entity Framework, değer nesnelerini karmaşık türler olarak ifade eder. Karmaşık türler kendi başına izlenemez.
Ancak Blog sınıfında bir özellik olarak, BlogDetailsBlog nesnesinin bir parçası olarak izlenecektir. Kodun önce bunu tanıması için sınıfını BlogDetails olarak ComplexTypeişaretlemeniz gerekir.
[ComplexType]
public class BlogDetails
{
public DateTime? DateCreated { get; set; }
[MaxLength(250)]
public string Description { get; set; }
}
Artık bu blog için Blog öğesini temsil etmek üzere sınıfına BlogDetails bir özellik ekleyebilirsiniz.
public BlogDetails BlogDetail { get; set; }
Veritabanında, Blog tablosu, BlogDetail özelliğinde bulunanlar da dahil olmak üzere blogun tüm özelliklerini içerecektir. Varsayılan olarak, her birinin başında "BlogDetail" karmaşık türünün adı yer alır.
Eşzamanlılık Kontrolü
ConcurrencyCheck yorumu, kullanıcı bir varlığı düzenlediğinde veya sildiğinde, veritabanında eşzamanlılık denetimi için bir veya daha fazla özelliği işaretlemenizi sağlar. EF Designer ile çalışıyorsanız, bu, bir özelliğin ConcurrencyMode değerini Fixed olarak ayarlamakla uyumlu olur.
ConcurrencyCheck öğesini BloggerName özelliğine ekleyerek nasıl çalıştığını görelim.
[ConcurrencyCheck, MaxLength(10, ErrorMessage="BloggerName must be 10 characters or less"),MinLength(5)]
public string BloggerName { get; set; }
Çağrıldığında SaveChanges, BloggerName alanındaki ConcurrencyCheck ek açıklaması nedeniyle bu özelliğin orijinal değeri güncellemeye dahil edilir. Komut, anahtar değerine ek olarak BloggerName'nin özgün değerine göre de filtreleyerek doğru satırı bulmaya çalışacaktır. Veritabanına gönderilen UPDATE komutunun kritik bölümleri aşağıdadır. Burada komutun, blog veritabanından alındığında özgün değer olan 1 ve PrimaryTrackingKey "Julie" değerini içeren satırı BloggerName güncelleştireceğini görebilirsiniz.
where (([PrimaryTrackingKey] = @4) and ([BloggerName] = @5))
@4=1,@5=N'Julie'
Bu sırada birisi blogun blogcu adını değiştirdiyse, bu güncelleştirme başarısız olur ve işlemeniz gereken bir DbUpdateConcurrencyException alırsınız.
TimeStamp
Eşzamanlılık denetimi için rowversion veya zaman damgası alanlarını kullanmak daha yaygındır. Ancak ek açıklamayı ConcurrencyCheck kullanmak yerine, özelliğin türü bayt dizisi olduğu sürece daha belirli TimeStamp bir ek açıklama kullanabilirsiniz. Code First, Timestamp özelliklerini ConcurrencyCheck özellikleriyle aynı şekilde ele alır, ancak aynı zamanda Code First'ün oluşturduğu veritabanı alanının null atanamaz olmasını da sağlar. Belirli bir sınıfta yalnızca bir zaman damgası özelliğine sahip olabilirsiniz.
Blog sınıfına aşağıdaki özelliği ekleme:
[Timestamp]
public Byte[] TimeStamp { get; set; }
, ilk olarak veritabanı tablosunda null atanamayan bir zaman damgası sütunu oluşturan kodla sonuçlanabilir.
Tablo ve Sütun
Veritabanını Code First'in oluşturmasına izin veriyorsanız, oluşturduğu tabloların ve sütunların adını değiştirmek isteyebilirsiniz. Ayrıca, mevcut bir veritabanıyla Code First'i de kullanabilirsiniz. Ancak, etki alanınızdaki sınıfların ve özelliklerin adlarının veritabanınızdaki tablo ve sütunların adlarına uyması her zaman söz konusu değildir.
Sınıfım Blog olarak adlandırılmış ve kurala göre, kod öncelikle bunu Blogs adlı bir tabloyla eşleyeceğini varsayar. Böyle bir durum söz konusu değilse, özniteliğine sahip Table tablonun adını belirtebilirsiniz. Örneğin, ek açıklama tablo adının InternalBlogs olduğunu belirtir.
[Table("InternalBlogs")]
public class Blog
Column anotasyonu, eşlenmiş bir sütunun özelliklerini belirtme konusunda daha yetkindir. Bir adı, veri türünü, hatta tabloda bir sütunun görüntülenme sırasını bile belirtebilirsiniz. Özniteliğin bir örneği aşağıda verilmiştir Column .
[Column("BlogDescription", TypeName="ntext")]
public String Description {get;set;}
Column özniteliğini TypeName DataType DataAnnotation ile karıştırmayın. DataType, kullanıcı arabirimi için kullanılan bir ek açıklamadır ve *Code First* tarafından yoksayılır.
Yeniden oluşturulduktan sonra tablo aşağıda verilmiştir. Tablo adı InternalBlogs olarak değiştirildi ve Description karmaşık türdeki sütun artık BlogDescriptionşeklindedir. Ad ek açıklamada belirtildiğinden, kod önce sütun adını karmaşık türün adıyla başlatma kuralını kullanmaz.
VeritabanıTarafındanOluşturulan
Önemli veritabanı özelliklerinden biri, hesaplanan özelliklere sahip olma özelliğidir. Code First sınıflarınızı hesaplanan sütunlar içeren tablolarla eşlerseniz, Entity Framework'ün bu sütunları güncelleştirmeyi denemesini istemezsiniz. Ancak, verileri ekledikten veya güncelleştirdikten sonra EF'nin bu değerleri veritabanından döndürmesini istiyorsunuz. Sınıfınızdaki bu özellikleri DatabaseGenerated annotasyonuyla ve Computed enum ile işaretleyebilirsiniz. Diğer sabit listeleri None ve Identity.
[DatabaseGenerated(DatabaseGeneratedOption.Computed)]
public DateTime DateCreated { get; set; }
Kod veritabanını ilk oluştururken bayt veya zaman damgası sütunlarında oluşturulan veritabanını kullanabilirsiniz, aksi takdirde kodun hesaplanan sütun için formülü belirleyemeyeceği için bunu yalnızca mevcut veritabanlarını işaret ederken kullanmanız gerekir.
Yukarıda varsayılan olarak, bir tamsayı olan anahtar özelliğinin veritabanında bir kimlik anahtarı haline geleceğini okudunuz. Bu, DatabaseGenerated ayarını DatabaseGeneratedOption.Identity olarak ayarlamakla aynı olacaktır. Kimlik anahtarı olmasını istemiyorsanız değerini olarak DatabaseGeneratedOption.Noneayarlayabilirsiniz.
Dizin
Not
EF6.1 ve Sonrası için - Index özniteliği Entity Framework 6.1'de kullanıma sunulmuştur. Önceki bir sürümü kullanıyorsanız bu bölümdeki bilgiler geçerli değildir.
IndexAttribute kullanarak bir veya daha fazla sütunda dizin oluşturabilirsiniz. Özniteliğin bir veya daha fazla özelliğe eklenmesi, EF'nin veritabanını oluştururken veritabanında karşılık gelen dizini oluşturmasına veya Code First Migrations kullanıyorsanız ilgili CreateIndex çağrılarının iskelesini oluşturmasına neden olur.
Örneğin, aşağıdaki kod veritabanındaki Posts tablosunun Rating sütununda bir dizin oluşturulmasına neden olur.
public class Post
{
public int Id { get; set; }
public string Title { get; set; }
public string Content { get; set; }
[Index]
public int Rating { get; set; }
public int BlogId { get; set; }
}
Varsayılan olarak, dizin IX_<özellik adı> (yukarıdaki örnekte IX_Rating) olarak adlandırılır. Yine de dizin için bir ad belirtebilirsiniz. Aşağıdaki örnek, dizinin olarak adlandırılması PostRatingIndexgerektiğini belirtir.
[Index("PostRatingIndex")]
public int Rating { get; set; }
Varsayılan olarak, dizinler benzersiz olmayanlardır, ancak bir dizinin benzersiz olması gerektiğini belirtmek için adlandırılmış parametresini kullanabilirsiniz IsUnique . Aşağıdaki örnek, User'nin oturum açma adı üzerinde benzersiz bir dizin tanıtır.
public class User
{
public int UserId { get; set; }
[Index(IsUnique = true)]
[StringLength(200)]
public string Username { get; set; }
public string DisplayName { get; set; }
}
Birden Çok Sütunlu Dizinler
Birden çok sütuna yayılan dizinler, belirli bir tablo için birden çok Dizin ek açıklamasında aynı ad kullanılarak belirtilir. Çok sütunlu dizinler oluşturduğunuzda, dizindeki sütunlar için bir sıra belirtmeniz gerekir. Örneğin, aşağıdaki kod üzerinde Rating çok sütunlu bir dizin oluşturur ve BlogId IX_BlogIdAndRating olarak adlandırılır.
BlogId dizindeki ilk sütun ve Rating ikinci sütundur.
public class Post
{
public int Id { get; set; }
public string Title { get; set; }
public string Content { get; set; }
[Index("IX_BlogIdAndRating", 2)]
public int Rating { get; set; }
[Index("IX_BlogIdAndRating", 1)]
public int BlogId { get; set; }
}
İlişki Öznitelikleri: InverseProperty ve ForeignKey
Not
Bu sayfa, Veri Ek Açıklamalarını kullanarak Code First modelinizde ilişkileri ayarlama hakkında bilgi sağlar. EF'teki ilişkiler ve ilişkileri kullanarak verilere erişme ve verileri işleme hakkında genel bilgi için bkz . İlişkiler ve Gezinti Özellikleri.*
Code First kuralı, modelinizdeki en yaygın ilişkileri ele alır, ancak bazı durumlarda yardıma ihtiyaç duyar.
Anahtar özelliğinin Blog sınıfındaki adını değiştirmek, Post ile olan ilişkisiyle ilgili bir sorun yarattı.
Veritabanı oluşturulurken, kod önce Post sınıfında BlogId özelliğini görür ve, bu özelliğin, sınıf adı artı Id ile eşleşen bir kurala göre Blog sınıfına yabancı anahtar olarak tanındığını fark eder. Ancak blog sınıfında özellik yoktur BlogId . Bunun çözümü, Post içinde bir gezinti özelliği oluşturmak ve ForeignKey DataAnnotation kullanarak, önce kodun iki sınıf arasındaki ilişkiyi nasıl kuracağını (Post.BlogId özelliğini kullanarak) ve veritabanındaki kısıtlamaların nasıl belirtileceğini anlamasına yardımcı olmaktır.
public class Post
{
public int Id { get; set; }
public string Title { get; set; }
public DateTime DateCreated { get; set; }
public string Content { get; set; }
public int BlogId { get; set; }
[ForeignKey("BlogId")]
public Blog Blog { get; set; }
public ICollection<Comment> Comments { get; set; }
}
Veritabanındaki kısıtlama, InternalBlogs.PrimaryTrackingKey ile Posts.BlogId arasında bir ilişki gösterir.
InverseProperty, sınıflar arasında birden çok ilişki olduğunda kullanılır.
Post sınıfında, bir blog gönderisini kimin yazdığını ve kimin düzenlediğini takip etmek isteyebilirsiniz. Post sınıfı için iki yeni gezinti özelliği aşağıdadır.
public Person CreatedBy { get; set; }
public Person UpdatedBy { get; set; }
Bu özellikler tarafından referans verilen Person sınıfını da eklemeniz gerekir.
Person sınıfı, kişi tarafından yazılan tüm gönderiler ve kişi tarafından güncellenen tüm gönderiler için birer gezinti özelliğine sahiptir Post.
public class Person
{
public int Id { get; set; }
public string Name { get; set; }
public List<Post> PostsWritten { get; set; }
public List<Post> PostsUpdated { get; set; }
}
İlk olarak kod, iki sınıftaki özellikleri kendi kendine eşleştiremez. veritabanı Posts tablosunda kişi için bir yabancı anahtar ve kişi için CreatedByUpdatedBy bir tane olmalıdır, ancak önce kod dört yabancı anahtar özelliği oluşturur: Person_Id, Person_Id1, CreatedBy_Id ve UpdatedBy_Id.
Bu sorunları düzeltmek için ek açıklamayı InverseProperty kullanarak özelliklerin hizalamasını belirtebilirsiniz.
[InverseProperty("CreatedBy")]
public List<Post> PostsWritten { get; set; }
[InverseProperty("UpdatedBy")]
public List<Post> PostsUpdated { get; set; }
Person özelliği, PostsWritten'ün, Post türüne başvurduğunu bildiği için Post.CreatedBy ile ilişkisini kurar. Benzer şekilde, PostsUpdated öğesine Post.UpdatedBybağlanır. Ve kod ilk olarak fazladan yabancı anahtar oluşturmaz.
Özet
DataAnnotations, yalnızca kod ilk sınıflarınızda istemci ve sunucu tarafı doğrulamasını açıklamanıza izin vermekle kalmaz, aynı zamanda kodun sınıflarınızla ilgili ilk olarak kendi kurallarına göre yapacağı varsayımları geliştirmenize ve hatta düzeltmenize de olanak sağlar. DataAnnotations ile yalnızca veritabanı şeması oluşturmayı yönlendirmekle kalmaz, aynı zamanda kod ilk sınıflarınızı önceden var olan bir veritabanına da eşleyebilirsiniz.
Bunlar çok esnek olsa da DataAnnotations'ın yalnızca kod ilk sınıflarınızda yapabileceğiniz en yaygın yapılandırma değişikliklerini sağladığını unutmayın. Bazı uç durumlarda sınıflarınızı yapılandırmak için, alternatif yapılandırma mekanizması olan Code First'in Fluent API'sine bakmanız gerekir.