Friday, 1 November 2024

What are data annotations, and how are they used in EF Core?

Data Annotations in Entity Framework Core (EF Core) are attributes you can apply directly to model properties and classes to configure the model and enforce data validation. They help define rules for the database schema, as well as validate data within the application. Data Annotations are part of the System.ComponentModel.DataAnnotations namespace, and EF Core uses them as a quick and declarative way to customize the model.

Common Data Annotations in EF Core

Here’s a breakdown of some commonly used Data Annotations and how they impact the EF Core model and database schema:

  1. Key Attribute: Specifies the primary key of an entity.


    public class Product { [Key] public int ProductId { get; set; } }

    Note: If a property named Id or {ClassName}Id exists, EF Core infers it as the primary key by convention. Using [Key] is only necessary for non-standard primary keys.

  2. Required Attribute: Marks a property as non-nullable, meaning the corresponding column in the database will not allow NULL values.


    public class Product { public int ProductId { get; set; } [Required] public string Name { get; set; } }
  3. MaxLength and StringLength Attributes: Specify the maximum length of a string property. MaxLength is used to set the database column’s max length, while StringLength can specify both minimum and maximum length for validation.


    public class Product { public int ProductId { get; set; } [MaxLength(50)] public string Name { get; set; } [StringLength(100, MinimumLength = 5)] public string Description { get; set; } }
  4. Column Attribute: Configures the column name, data type, and order within the table.


    public class Product { public int ProductId { get; set; } [Column("Product_Name", TypeName = "nvarchar(50)")] public string Name { get; set; } }
  5. ForeignKey Attribute: Used to specify the foreign key property for a relationship, especially in cases where the naming conventions do not match.


    public class Product { public int ProductId { get; set; } public int CategoryId { get; set; } [ForeignKey("CategoryId")] public Category Category { get; set; } }
  6. InverseProperty Attribute: Useful for self-referencing relationships or where there are multiple navigation properties between two entities.


    public class Employee { public int EmployeeId { get; set; } [InverseProperty("Manager")] public List<Employee> Subordinates { get; set; } [InverseProperty("Subordinates")] public Employee Manager { get; set; } }
  7. NotMapped Attribute: Excludes a property from being mapped to a database column. This is useful for properties that are used only within the application logic and should not be stored in the database.


    public class Product { public int ProductId { get; set; } [NotMapped] public string TemporaryProperty { get; set; } }
  8. ConcurrencyCheck Attribute: Marks a property as part of the concurrency token. EF Core will check for changes to this column to detect concurrency conflicts.


    public class Product { public int ProductId { get; set; } [ConcurrencyCheck] public int Stock { get; set; } }
  9. Timestamp Attribute: Marks a byte array property as a timestamp for concurrency control, used to detect conflicts during updates.


    public class Product { public int ProductId { get; set; } [Timestamp] public byte[] RowVersion { get; set; } }

Example of Using Data Annotations in EF Core

Here’s a full example of a Product entity class with various Data Annotations:


using System; using System.Collections.Generic; using System.ComponentModel.DataAnnotations; using System.ComponentModel.DataAnnotations.Schema; public class Product { [Key] public int ProductId { get; set; } [Required] [MaxLength(100)] [Column("Product_Name", TypeName = "nvarchar(100)")] public string Name { get; set; } [StringLength(500)] public string Description { get; set; } [Range(0, 9999.99)] public decimal Price { get; set; } [ForeignKey("CategoryId")] public int CategoryId { get; set; } public Category Category { get; set; } [Timestamp] public byte[] RowVersion { get; set; } }

Advantages of Using Data Annotations in EF Core

  • Simplicity: Data Annotations provide a quick way to set up constraints, relationships, and rules without extensive Fluent API configuration.
  • Readability: Annotations directly within the model class make the configuration more readable and accessible.
  • Validation: Attributes like Required, Range, and StringLength also work as validation attributes, helping enforce data integrity before data reaches the database.

Interview Question Examples on Data Annotations in EF Core

  1. What is the difference between MaxLength and StringLength?

    • Answer: MaxLength specifies the maximum length of a string or array and is mostly used for setting database column size, whereas StringLength can specify both minimum and maximum length constraints and is used for data validation in addition to setting column size.
  2. When would you use the NotMapped attribute?

    • Answer: NotMapped is used when you want a property in your model that is not stored in the database. This is helpful for properties that are only used for calculations, temporary data storage, or other purposes within the application logic.
  3. How does the Timestamp attribute help with concurrency in EF Core?

    • Answer: The Timestamp attribute marks a byte array property as a concurrency token, which EF Core uses to detect if a record has been modified by another user before it allows an update, thus preventing conflicting updates.
Share:

0 comments:

Post a Comment