Fluent API 配置實體和資料庫之間的對映關係

剑小秀發表於2024-05-20

1. 配置主鍵

protected override void OnModelCreating(ModelBuilder modelBuilder)
{
    modelBuilder.Entity<Blog>()
        .HasKey(b => b.BlogId); // 配置Blog實體的主鍵為BlogId
}

2. 配置屬性和列

protected override void OnModelCreating(ModelBuilder modelBuilder)
{
    modelBuilder.Entity<Blog>()
        .Property(b => b.Url)
        .HasColumnName("BlogUrl") // 配置Url屬性對映到資料庫中的BlogUrl列
        .HasMaxLength(200) // 設定列的最大長度為200
        .IsRequired(); // 設定該列在資料庫中不允許為空
}

3. 配置一對多關係

protected override void OnModelCreating(ModelBuilder modelBuilder)
{
    modelBuilder.Entity<Blog>()
        .HasMany(b => b.Posts) // 配置Blog有一個Posts集合屬性
        .WithOne(p => p.Blog) // 配置Post有一個Blog導航屬性
        .HasForeignKey(p => p.BlogId); // 配置外來鍵為Post實體的BlogId屬性
}

4. 配置多對多關係(透過聯接實體)

protected override void OnModelCreating(ModelBuilder modelBuilder)
{
    modelBuilder.Entity<Student>()
        .HasMany(s => s.Courses)
        .WithMany(c => c.Students)
        .UsingEntity<Enrollment>(
            j => j
                .HasOne(e => e.Student)
                .WithMany(s => s.Enrollments)
                .HasForeignKey(e => e.StudentId),
            j => j
                .HasOne(e => e.Course)
                .WithMany(c => c.Enrollments)
                .HasForeignKey(e => e.CourseId),
            j =>
            {
                j.ToTable("StudentCourse"); // 設定聯接表的名稱
            });
}

public class Enrollment
{
    public int StudentId { get; set; }
    public Student Student { get; set; }

    public int CourseId { get; set; }
    public Course Course { get; set; }

    // 可以新增其他屬性,比如成績等
}

5. 配置索引

protected override void OnModelCreating(ModelBuilder modelBuilder)
{
    modelBuilder.Entity<Blog>()
        .HasIndex(b => b.Url) // 為Url屬性建立索引
        .IsUnique(); // 設定索引為唯一
}

6. 配置複合主鍵和索引

protected override void OnModelCreating(ModelBuilder modelBuilder)
{
    modelBuilder.Entity<SomeEntity>()
        .HasKey(e => new { e.Key1, e.Key2 }); // 配置複合主鍵

    modelBuilder.Entity<SomeEntity>()
        .HasIndex(e => new { e.Key1, e.Key2 }) // 配置複合索引
        .IsUnique(); // 設定索引為唯一
}

7. 配置資料註解與Fluent API混合使用

你可以同時使用資料註解(Data Annotations)和Fluent API來配置實體。Fluent API提供了更多的靈活性和更精細的控制,而資料註解則提供了更簡潔的配置方式。例如:

[Table("Blogs")] // 使用資料註解配置表名
public class Blog
{
    public int BlogId { get; set; }
    public string Url { get; set; }
    // ... 其他屬性 ...
}
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
    modelBuilder.Entity<Blog>()
        .Property(b => b.Url)
        .HasMaxLength(200); // 使用Fluent API配置Url屬性的最大長度
    // ... 其他配置 ...
}

在實際開發中,你可以根據專案的具體需求和團隊偏好選擇使用資料註解還是Fluent API,或者兩者混合使用。通常,對於簡單的配置可以使用資料註解,而對於需要更精細控制的場景則使用Fluent API。

對於您提供的模型,如果您想使用 Fluent API 來配置 PrivilegeGroupPrivilege 之間的關係,您可以這樣做:

using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Metadata.Builders;
using System.Collections.Generic;

namespace Model
{
    public class PrivilegeGroup
    {
        public int Id { get; set; }
        public string GroupName { get; set; }
        public virtual List<Privilege> Privileges { get; set; }
    }

    public class Privilege
    {
        public int Id { get; set; }
        public int PrivilegeGroupId { get; set; }
        public string PrivilegeName { get; set; }
        public virtual PrivilegeGroup PrivilegeGroup { get; set; }
    }

    public class YourDbContext : DbContext
    {
        public DbSet<PrivilegeGroup> PrivilegeGroups { get; set; }
        public DbSet<Privilege> Privileges { get; set; }

        protected override void OnModelCreating(ModelBuilder modelBuilder)
        {
            // 配置 PrivilegeGroup 實體
            modelBuilder.Entity<PrivilegeGroup>(ConfigurePrivilegeGroup);

            // 配置 Privilege 實體
            modelBuilder.Entity<Privilege>(ConfigurePrivilege);
        }

        private void ConfigurePrivilegeGroup(EntityTypeBuilder<PrivilegeGroup> builder)
        {
            // 配置主鍵
            builder.HasKey(pg => pg.Id);

            // 配置 GroupName 為唯一索引
            builder.HasIndex(pg => pg.GroupName).IsUnique();

            // 配置與 Privilege 之間的關係(一對多)
            builder.HasMany(pg => pg.Privileges)
                   .WithOne(p => p.PrivilegeGroup)
                   .HasForeignKey(p => p.PrivilegeGroupId);
        }

        private void ConfigurePrivilege(EntityTypeBuilder<Privilege> builder)
        {
            // 配置主鍵
            builder.HasKey(p => p.Id);

            // 配置外來鍵
            builder.HasOne(p => p.PrivilegeGroup)
                   .WithMany(pg => pg.Privileges)
                   .HasForeignKey(p => p.PrivilegeGroupId);
        }
    }
}

在這個例子中,PrivilegeGroupPrivilege 之間的關係被配置為一對多關係。Privilege 實體包含一個名為 PrivilegeGroupId 的外來鍵屬性,該屬性引用 PrivilegeGroup 實體的 Id 屬性。

ConfigurePrivilegeGroupConfigurePrivilege 方法分別用於配置 PrivilegeGroupPrivilege 實體的對映關係。在 ConfigurePrivilegeGroup 方法中,我們使用 HasIndex 方法來配置 GroupName 為唯一索引,並使用 HasManyWithOne 方法來配置一對多關係。在 ConfigurePrivilege 方法中,我們使用 HasOneWithMany 方法來配置多對一關係,並指定外來鍵屬性。

透過這種方式,您可以完全透過 Fluent API 來配置實體和資料庫之間的對映關係,而不是依賴資料註解。這提供了更多的靈活性和控制力,特別是在處理複雜的模型和資料庫結構時。

相關文章