Convention-Based Configuration
Core Mapping Rules
- Table names correspond to the
DbSetproperty names defined in yourDbContext - Column names derive from entity property names, with data types selected based on the most compatible match for the property type (customizable)
- Column nullability aligns with the underlying property's nullability setting
- Properties named
Idautomatically become primary keys- Integer-based keys (
short,int,long) utilize auto-increment behavior by default Guidprimary keys leverage theGuidgeneration mechanism
- Integer-based keys (
Configuration Approaches
Combined Usage
Both methods share overlapping functionality and can be used together, though this approach is generally discouraged.
Data Annotations
Attributes applied directly to entity classes provide a straightforward but tightly coupled configuration method.
[Table("T_Books")]
public class Book
{
public long Id { get; set; }
[Required]
[MaxLength(50)]
public string Title { get; set; }
public DateTime PubTime { get; set; }
public double Price { get; set; }
[Required]
[MaxLength(50)]
public string AuthorName { get; set; }
}
Fluent API with Separate Configuration Classes
Extracting configuration into dedicated classes promotes separation of concerns and improves maintainability. This is the recommended approach.
public class BookConfiguration : IEntityTypeConfiguration<Book>
{
public void Configure(EntityTypeBuilder<Book> builder)
{
builder.ToTable("T_Books");
builder.Property(b => b.Title).HasMaxLength(50).IsRequired();
builder.Property(b => b.AuthorName).HasMaxLength(20).IsRequired();
}
}
public class LibraryDbContext : DbContext
{
public DbSet<Book> Books { get; set; }
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
base.OnConfiguring(optionsBuilder);
optionsBuilder.UseSqlServer("Server=.;Database=demo1;Trusted_Connection=True;MultipleActiveResultSets=true");
}
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
base.OnModelCreating(modelBuilder);
modelBuilder.ApplyConfigurationsFromAssembly(this.GetType().Assembly);
}
}
Fluent API Reference
Table Views
Map entities to database views. This approach is not recommended for most scenarios.
modelBuilder.Entity<Blog>().ToView("blogsView");
Excluding Properties from Mapping
Prevent specific properties from being persisted to the database.
public class BookConfiguration : IEntityTypeConfiguration<Book>
{
public void Configure(EntityTypeBuilder<Book> builder)
{
builder.ToTable("T_Books");
builder.Ignore(b => b.Price);
}
}
Customizing Column Names
public class BookConfiguration : IEntityTypeConfiguration<Book>
{
public void Configure(EntityTypeBuilder<Book> builder)
{
builder.ToTable("T_Books");
builder.Property(b => b.PubTime).HasColumnName("pub_time");
}
}
modelBuilder.Entity<Book>().Property(b => b.Title).HasColumnName("book_title");
Specifying Column Data Types
public class BookConfiguration : IEntityTypeConfiguration<Book>
{
public void Configure(EntityTypeBuilder<Book> builder)
{
builder.ToTable("T_Books");
builder.Property(b => b.Title).HasColumnType("varchar(200)");
}
}
Primary Key Configuration
By default, properties named Id or EntityNameId serve as primary keys. Use HasKey() to override this behavior. Composite keys are supported but discouraged.
public class BookConfiguration : IEntityTypeConfiguration<Book>
{
public void Configure(EntityTypeBuilder<Book> builder)
{
builder.ToTable("T_Books");
builder.HasKey(b => b.Id);
}
}
public class LibraryDbContext : DbContext
{
public DbSet<Book> Books { get; set; }
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
// ...
}
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
base.OnModelCreating(modelBuilder);
modelBuilder.Entity<Book>().HasKey(x => x.Id);
}
}
Configuring Value Generation
For computed columns and similar scenarios. This feature is generally not recommended.
builder.Property(b => b.Price).ValueGeneratedOnAdd();
Setting Default Values
builder.Property(b => b.Title).HasDefaultValue("Untitled");
modelBuilder.Entity<Book>().Property(b => b.Title).HasDefaultValue("Untitled");
Index Configuration
Standard Index
builder.HasIndex(b => b.Title);
modelBuilder.Entity<Book>().HasIndex(b => b.Title);
Composite Index
builder.HasIndex(b => new { b.Id, b.Title });
modelBuilder.Entity<Book>().HasIndex(b => new { b.Id, b.Title });
Unique Index
builder.HasIndex(b => b.Title).IsUnique();
modelBuilder.Entity<Book>().HasIndex(b => b.Title).IsUnique();
Clustered Index
builder.HasIndex(b => b.Title).IsClustered();
modelBuilder.Entity<Book>().HasIndex(b => b.Title).IsClustered();
Method Chaining Considerations
Chained method calls require that each preceding method returns an object capable of invoking the next method in the chain.