by GeeksArray
In this blog post you will use DataAnnotations to configure pre-defined rules and constraints for tables which will be created through EF Core Code First.
DataAnnotations is a group of classes, attributes, methods. DataAnnotations are used to decorate classes and properties to enforce pre-defined validation rules. It can be used in ASP.NET MVC, Web Forms, Web API applications. Classes related to DataAnnotations belong to System.ComponentModel.DataAnnotations and System.ComponentModel.DataAnnotations.Schema namespace.
public DbSetCategories { get; set; }
You can change the name of a table by applying Table attribute to the Category entity class. You can use the Schema property to specify the table schema.
using System.ComponentModel.DataAnnotations.Schema; [Table("ProductCategory", Schema="Admin")] public class Category { }
The column attribute can be applied to entity properties to define the column name, data type, order in database table.
Column attribute overrides default conventions.
public class Category { public Category() { } [Column("CategoryID", Order = 0, TypeName="int")] public int CategoryID { get; set; } [Column("CategoryName", Order = 1, TypeName="varchar2")] public string CategoryName { get; set; } [Column("CategoryName", Order = 2, TypeName="varchar2")] public string Description { get; set; } }
You can use Key attributes to multiple columns to make CompositeKey with column Order specified.
public class Product { public Product() { } [Column("ProductId", Order = 0, TypeName="int")] public int ProductID { get; set; } [Column("CategoryID", Order = 1, TypeName="int")] public int CategoryID { get; set; } }
public class Product { public Product() { } public int ProductID { get; set; } [NotMapped] public int ProductDiscountValue { get; set; } }
The attribute is used to configure referential integrity or foreign key relationship between two tables.
By default Entity Framework makes a property as a foreign key when it is matching with Primary Key of the related entity.
You can implement the foreign Key attribute as.
public class Category { [Key] public int CategoryID { get; set; } public string CategoryName { get; set; } public string Description { get; set; } public ICollection<Product> Products { get; set; } } public class Product { [Key] public int ProductID { get; set; } [ForeignKey("Category")] public int CategoryID { get; set; } public virtual Category Category { get; set; } }
Index Data Annotation attribute creates cluster or non cluster index on the column. You can configure index name, cluster and unique index as shown in below code snippet.
public class Product { [Key] public int ProductID { get; set; } [Index("Idx_CategoryID", IsClustered=false, IsUnique=false )] public int CategoryID { get; set; } }
The required attribute is used to create columns with NOT NULL constraints. If the application tryies to update data with NULL value on these columns, it throws Microsoft.EntityFrameworkCore.DbUpdateException.
public class Product { public Product() { } [key] public int ProductID { get; set; } [Required] public string ProductName { get; set; } [Required] public int CategoryID { get; set; } [Required] public int QuantityPerUnit { get; set; } public decimal UnitPrice { get; set; } }
MaxLength attribute is used to specify the maximum size of the string or byte[] type.
Below code, snippet shows how to use the MaxLength Data Annotation attribute. Maximum size for CategoryName column has set as 50 characters and the Description column has set as 250 characters.
public class Category { public Category() { } [Key] public int CategoryID { get; set; } [MaxLength(50)] public string CategoryName { get; set; } [MaxLength(250)] public string Description { get; set; } public virtual List<Products> Products { get; set; } }
EF Core will throw Microsoft.EntityFrameworkCore.DbUpdateException if the application tries to use the length more than value of the MaxLength attribute.
StringLength Data Annotations attribute can be used only for string properties of the entity class. When you set the StringLength attribute, Entity Framework will set the column's maximum allowed the size in table.
You can use StringLength as shown in below code.
public class Category { public Category() { } [Key] public int CategoryID { get; set; } [StringLength(50)] public string CategoryName { get; set; } [StringLength(250, MinimumLength = 5)] public string Description { get; set; } public virtual List<Products> Products { get; set; } }
EF Core will throw Microsoft.EntityFrameworkCore.DbUpdateException if the application tries to use the length more than value of StringLength attribute.
Timestamp Data Annotations attribute can be used only with byte array type properties. Entity Framework will create a table with the timestamp and use it automatically for concurrency check while executing update statements.
TimeStamp can be applied only for one property in an entity class. It guarantees a row with a unique value for TimeStamp type property in the database.
Implementation of TimeStamp attribute
public class Product { public Product() { } [Key] public int ProductID { get; set; } [Timestamp] public byte[] ProductVersion {get; set;} }
ConcurrencyCheck Data Annotation gives you a very good way to handle conflicts that can occur when multiple users try to update / delete same data.
This attribute can be used with multiple properties in entity class and with any data type whereas TimeStamp can be applied with only one property and only with Byte[] data type.
public class Product { public Product() { } [key] public int ProductID { get; set; } [ConcurrencyCheck] public string ProductName { get; set; } }
In above example for property ProductName attribute ConcurrencyCheck is used. Entity framework will use ProductName column to handle concurrency.
Here is the real time scenario of Concurrency. User1 and User2 are reading details about the product having ProductName as "Product 1".
User1 changes ProductName from "Product 1" to "Product 2", then User2 tries to change ProductName as "Product 3" however User2 did not read or do not have the latest committed changes Entity Framework throws DbConcurrencyException.
In this case, Entity Framework will add additional WHERE Clause for column ProductName. So when User2 tries to update the same product it's query becomes as shown below which will return zero records because User1 already committed ProductName as "Product 2".
UPDATE Products SET ProductName = 'Product 3' WHERE ProductID = 3 and ProductName = 'Product 1'