"Code-First Domain class oluşturmak için sıkça kullanılan dataannotation attiribut'ler veritabanının nesnel kopyaları sayılabilirler. Bu bağlamda datanın oluşması için gerekli olan malzemenin kural kısmıdır denilebilir. Şimdi bu attirbut'leri inceleyelim;"
İlgili entity ile ilgili belirtmek istediğimiz property’i key olarak tanıtmak için kullanılır.
using System.ComponentModel.DataAnnotations; public class Student { public Student() { } [Key] public int StudentKey { get; set; } public string StudentName { get; set; } }
yukardaki örneğe göre PackageId alanı key olarak tanımlanmış oldu.
Birden fazla alan Key olarak işaretlenebilir, ancak kullanım olarak Column Attribute’i ile tanımlanır.
using System.ComponentModel.DataAnnotations; public class Student { public Student() { } [Key] [Column(Order = 1)] public int StudentKey1 { get; set; } [Key] [Column(Order = 2)] public int StudentKey2 { get; set; } public string StudentName { get; set; } }
Eğer sadece tek bir integer alan Key olarak işaretlenmişse bu alan aynı zamanda identity olarak da belirlenir. yani sayı otomatik olarak üretilir. Birden fazla alanın identity olarak işaretlendiği key yapılarında bu alanlardan herhangi biri identity olarak işaretlenmez.
Domain Class içinde sadece tek bir alanda olabilir. TimeStamp attribute timestamp tipinde bir kolon oluşturur Code-First bu kolonu concurency check için otomatik olarak kullanır.
using System.ComponentModel.DataAnnotations; public class Student { public Student() { } public int StudentKey { get; set; } public string StudentName { get; set; } [TimeStamp] public byte[] RowVersion { get; set; } }
Bu alan birden fazla kullanıcının aynı kaydın farklı versiyonlarını kaydetmek istedikleri zaman concurency kontrollerini hızlıca yapmak için kullanılır. timestamp attribute’undan farklı olarak birden fazla alan concurencycheck olarak işaretlenebilir.
using System.ComponentModel.DataAnnotations; public class Student { public Student() { } public int StudentId { get; set; } [ConcurrencyCheck] public string StudentName { get; set; } }
sonuç olarak oluşacak olan sql sorgusu aşağıdaki şekilde olacaktır.
exec sp_executesql N'UPDATE [dbo].[Students] SET [StudentName] = @0 WHERE(([StudentId] = @1) AND([StudentName] = @2)) ',N'@0 nvarchar(max) ,@1 int,@2 nvarchar(max) ',@0=N'Steve ',@1=1,@2=N'Bill ' go
Tanımlanan alanı not null olarak işaretleyerek bu alana mutlaka bir değer girilmesini garanti eder.
using System.ComponentModel.DataAnnotations; public class Student { public Student() { } public int StudentID { get; set; } [Required] public string StudentName { get; set; } }
Maxlength attribute’u strting yada array tipli propertylere uygulanabilir. Bu attribute ile ilgili kolonunun alan uzunluğu sql’de set edilir.
using System.ComponentModel.DataAnnotations; public class Student { public Student() { } public int StudentID { get; set; } [MaxLength(50)] public string StudentName { get; set; } }
Entity framework belirlenen uzunluğun aşılması durumunda EntityValidationError throw edilir.
MinLength attribute’u bir validation attribute’dür. belirlenen uzunluktan daha az bir değer girilmesi durumunda yine EntityValidationError throw edilir.
using System.ComponentModel.DataAnnotations; public class Student { public Student() { } public int StudentID { get; set; } [MaxLength(50), MinLength(2)] public string StudentName { get; set; } }
Maxlength ile hemen hemen aynıdır. Sadece string propertylerde kullanılabilir.
using System.ComponentModel.DataAnnotations; public class Student { public Student() { } public int StudentID { get; set; } [StringLength(50)] public string StudentName { get; set; } }
Table attribute bir class’a tanımlanabilir. Default olarak CodeFirst table isimlerini classname’den üretir ancak bu attribute ile belirlenen isimle bu tablo ismi overwrite edilir.
using System.ComponentModel.DataAnnotations.Schema; [Table("StudentMaster")] public class Student { public Student() { } public int StudentID { get; set; } public string StudentName { get; set; } }
aynı zamanda tablo ismi schema ismi de aşağıdaki şekilde kullanılabilir.
using System.ComponentModel.DataAnnotations.Schema; [Table("StudentMaster", Schema = "Admin")] public class Student { public Student() { } public int StudentID { get; set; } public string StudentName { get; set; } }
bu durumda yukardaki örneğe göre tablo Admin scheması içersinde Admin.StudentMaster şeklinde olacaktır.
Column attribute’ü propertylere uygulanabilir. Default olarak property isimleri ile tabloda field isimleri oluşur. Ancak kolon ismin farklı vermek istersek columns atribute kullanılır.
using System.ComponentModel.DataAnnotations.Schema; public class Student { public Student() { } public int StudentID { get; set; } [Column("Name")] public string StudentName { get; set; } }
Aynı zamanda Order ve Typename alanları aşağıdaki şekilde set edilerek de kullanılabilir.
using System.ComponentModel.DataAnnotations.Schema; public class Student { public Student() { } public int StudentID { get; set; } [Column("Name", Order = 1, TypeName = "varchar")] public string StudentName { get; set; } }
ForeignKey attribute propertylere uygulanır. Default olarak code-first entity linklerini otomatik olarak uygular ve FK alanlarını otomatik olarak oluşturur.
public class Student { public Student() { } public int StudentID { get; set; } public string StudentName { get; set; } //Foreign key for Standard public int StandardId { get; set; } public Standard Standard { get; set; } } public class Standard { public Standard() { } public int StandardId { get; set; } public string StandardName { get; set; } public ICollection<Student> Students { get; set; } }
ForeignKey attribute bu tanımlamayı overwrite eder bu alan için farklı isimli FK alanlarını oluşturmaya olanak sağlar.
public class Student { public Student() { } public int StudentID { get; set; } public string StudentName { get; set; } //Foreign key for Standard public int StandardRefId { get; set; } [ForeignKey("StandardRefId")] public Standard Standard { get; set; } } public class Standard { public Standard() { } public int StandardId { get; set; } public string StandardName { get; set; } public ICollection<Student> Students { get; set; } }ForeignKey attribute’ü key property noktasında da aşağıdaki şekilde tanımlanabilir.public class Student { public Student() { } public int StudentID { get; set; } public string StudentName { get; set; } //Foreign key for Standard [ForeignKey("Standard")] public int StandardRefId { get; set; } public Standard Standard { get; set; } } public class Standard { public Standard() { } public int StandardId { get; set; } public string StandardName { get; set; } public ICollection<Student> Students { get; set; } }
NotMapped attribute propertylere uygulanır. Default olarak code first get ve set propertyleri olan tüm kolonları tabloda oluşturur NotMapped attribute’ü uygulanarak belli bir alanın tablo’da oluşturulması engellenir.
using System.ComponentModel.DataAnnotations; public class Student { public Student() { } public int StudentId { get; set; } public string StudentName { get; set; } [NotMapped] public int Age { get; set; } }
Bununla birlikte Code-First default olarak get yada set propery’si olmayan alanları tabloda bir field olarak açmaz.
using System.ComponentModel.DataAnnotations; public class Student { public Student() { } private int _age = 0; public int StudentId { get; set; } public string StudentName { get; set; } public string FirstName { get { return StudentName; } } public string Age { set { _age = value; } } }
Code-First Foreignkey alanlarının isimlerini {classname}_{PrimaryKey} formülünü kullanarak oluşturur.
public class Student { public Student() { } public int StudentID { get; set; } public string StudentName { get; set; } public Standard CurrentStandard { get; set; } public Standard PreviousStandard { get; set; } } public class Standard { public Standard() { } public int StandardId { get; set; } public string StandardName { get; set; } public ICollection<Student> CurrentStudents { get; set; } public ICollection<Student> PreviousStudents { get; set; } }
InverseProperty attribute’ü bu tanımlamayı override eder. bu durumda sonuç aşağıdaki şekilde olacaktır.
public class Student { public Student() { } public int StudentID { get; set; } public string StudentName { get; set; } public Standard CurrentStandard { get; set; } public Standard PreviousStandard { get; set; } } public class Standard { public Standard() { } public int StandardId { get; set; } public string StandardName { get; set; } [InverseProperty("CurrentStandard")] public ICollection<Student> CurrentStudents { get; set; } [InverseProperty("PreviousStandard")] public ICollection<Student> PreviousStudents { get; set; } }
Yine foreignkey attribute’ü ile aşağıdaki şekilde kullanılabilir. her iki durumda da sonuç aynı olacaktır.
public class Student { public Student() { } public int StudentID { get; set; } public string StudentName { get; set; } public int CurrentStandardId { get; set; } public int PreviousStandardId { get; set; } [ForeignKey("CurrentStandardId")] public Standard CurrentStandard { get; set; } [ForeignKey("PreviousStandardId")] public Standard PreviousStandard { get; set; } } public class Standard { public Standard() { } public int StandardId { get; set; } public string StandardName { get; set; } [InverseProperty("CurrentStandard")] public ICollection<Student> CurrentStudents { get; set; } [InverseProperty("PreviousStandard")] public ICollection<Student> PreviousStudents { get; set; } }