Friday, 7 February 2025

Manually Map Read Only Entity in Entity Framework Core

We will see how to map a Database Table to EF Core without creating a View. EF Core used in this writing is version 9.0.0.

First we create the entity that we want to map:
public class ReadOnlyCampus
{
    public long UniversityCampusId { get; set; }
    public long UniversityId { get; set; }
    public string CampusName { get; set; }
    public bool IsActive { get; set; }
}

Then we create a new partial class for Database Context file. We could save this file as 'Partial_StudentContext.cs' if the main partial class (generated one) is 'StudentContext.cs'. This is so that our manual mappings and configurations will not be overwritten when we run 'Scaffold-DbContext' command next time.
public partial class StudentContext
{
	// add the DbSet for the entity
    public virtual DbSet<ReadOnlyCampus> ReadOnlyCampuses { get; set; }

	// this is extension from the partial method OnModelCreatingPartial(ModelBuilder modelBuilder) declared in the main context file
    partial void OnModelCreatingPartial(ModelBuilder modelBuilder)
    {
        modelBuilder.Entity<ReadOnlyCampus>(entity =>
        {
            entity.HasNoKey(); // indicate that this entity does not have a primary key
            entity.ToTable("UniversityCampus"); // map to the Database Table 'UniversityCampus'

			// map the properties that we need
            entity.Property(e => e.UniversityCampusId).HasColumnName("UniversityCampusId");
            entity.Property(e => e.UniversityId).HasColumnName("UniversityId");
            entity.Property(e => e.CampusName).HasColumnName("CampusName");
            entity.Property(e => e.IsActive).HasColumnName("IsActive");
        });
    }

    public override int SaveChanges()
    {
		// we make sure that this entity cannnot be changed
        foreach (var entry in ChangeTracker.Entries<ReadOnlyCampus>())
        {
            switch (entry.State)
            {
                case EntityState.Added:
                case EntityState.Modified:
                case EntityState.Deleted:
                    entry.State = EntityState.Unchanged;
                    break;
            }
        }

        return base.SaveChanges();
    }
}

Then we will be able to query this entity like other normal EF entity.