Entities & Data Models
Level: Beginner
ℹ️ Where This Fits
Entity models are C# classes that map to database tables. Configuring them with data annotations or Fluent API defines the database schema automatically.
ℹ️ What You'll Learn
- Entity class: C# class representing database table (Student class = Students table)
- Property mapping: Class properties become table columns
- Key attribute:
[Key]marks primary key property - Required attribute:
[Required]makes column NOT NULL - MaxLength:
[MaxLength(100)]limits string column length - Column attribute:
[Column("StudentName")]maps property to different column name - Table attribute:
[Table("tbl_Students")]maps class to different table name - Default values:
[DefaultValue(true)]orHasDefaultValue()in Fluent API - Data types: Property type maps to SQL type (string→NVARCHAR, int→INT, DateTime→DATETIME)
- Computed columns:
[Computed]for SQL-calculated columns - Navigation properties:
public List<Exam> Exams { get; set; }for relationships - Foreign key:
[ForeignKey("StudentId")]marks foreign key property - School Management entities: Student, Teacher, Exam, ExamResult, Fee, FeePayment, Attendance
- Fluent API: Alternative to data annotations (
modelBuilder.Entity<Student>()...) - Common mistakes: Forgetting primary key, using nullable reference types incorrectly, circular references
Basic Student Entity
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
public class Student
{
[Key]
public int Id { get; set; }
[Required]
[MaxLength(100)]
public string Name { get; set; } = string.Empty;
[Required]
[MaxLength(10)]
public string ClassName { get; set; } = string.Empty;
[Required]
[MaxLength(20)]
public string RollNumber { get; set; } = string.Empty;
public DateTime DateOfBirth { get; set; }
[Required]
public StudentStatus Status { get; set; } = StudentStatus.Active;
public DateTime CreatedAt { get; set; } = DateTime.UtcNow;
// Navigation properties
public List<Exam> Exams { get; set; } = new();
public List<FeeAccount> FeeAccounts { get; set; } = new();
public List<Attendance> Attendance { get; set; } = new();
}
public enum StudentStatus { Active, Inactive, Graduated, Transferred }
Exam Entity with Foreign Key
public class Exam
{
[Key]
public int Id { get; set; }
[Required]
[MaxLength(100)]
public string ExamName { get; set; } = string.Empty;
[Required]
public ExamType Type { get; set; }
public DateTime ExamDate { get; set; }
public int MaxMarks { get; set; }
// Foreign key to Subject
[ForeignKey("Subject")]
public int SubjectId { get; set; }
public Subject Subject { get; set; }
// Navigation properties
public List<ExamResult> Results { get; set; } = new();
}
public enum ExamType { UnitTest, MidTerm, Final, Practical }
Many-to-Many Example - Student and Subject
public class Student
{
public int Id { get; set; }
public string Name { get; set; }
// Many-to-many with Subject through StudentSubject junction table
public List<StudentSubject> StudentSubjects { get; set; } = new();
}
public class Subject
{
public int Id { get; set; }
public string Name { get; set; }
public List<StudentSubject> StudentSubjects { get; set; } = new();
}
public class StudentSubject
{
public int StudentId { get; set; }
public Student Student { get; set; }
public int SubjectId { get; set; }
public Subject Subject { get; set; }
// Composite primary key
}
Fluent API Configuration
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
// Student configuration
modelBuilder.Entity<Student>(entity =>
{
entity.HasKey(e => e.Id);
entity.Property(e => e.Name)
.IsRequired()
.HasMaxLength(100);
entity.Property(e => e.ClassName)
.IsRequired()
.HasMaxLength(10);
entity.HasMany(e => e.Exams)
.WithOne()
.OnDelete(DeleteBehavior.Cascade);
});
// Exam configuration
modelBuilder.Entity<Exam>(entity =>
{
entity.HasKey(e => e.Id);
entity.HasOne(e => e.Subject).WithMany();
});
// StudentSubject (many-to-many)
modelBuilder.Entity<StudentSubject>(entity =>
{
entity.HasKey(e => new { e.StudentId, e.SubjectId });
entity.HasOne(e => e.Student)
.WithMany(s => s.StudentSubjects)
.HasForeignKey(e => e.StudentId);
entity.HasOne(e => e.Subject)
.WithMany(s => s.StudentSubjects)
.HasForeignKey(e => e.SubjectId);
});
}
Best Practices
✓ Always define primary keys
✓ Use [Required] for NOT NULL columns
✓ Use [MaxLength] for string limits
✓ Initialize collections in property initializer
✓ Use = string.Empty for required strings
💡 Nullable Reference Types
Enable nullable reference types in .csproj:
<PropertyGroup>
<Nullable>enable</Nullable>
</PropertyGroup>
Then use string? for optional, string for required.
🤖Use AI to Learn Faster
Use ChatGPT, Claude, or Copilot to go deeper on Entities & Data Models. Try these prompts:
"What's the difference between data annotations and Fluent API?""How do you define a many-to-many relationship?""What does the [Key] attribute do?""How do you set a default value for a column?"
💡 Tip: After reading this article, paste your own code into AI and ask "What could go wrong here and why?" — fastest way to find edge cases and deepen understanding.
Next Article
nexcoding.in
Have questions on your tech stack, ongoing projects, or need one-to-one training?