You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

ASP.NET Core 6 MVC中EF关联两主表创建权限详情表的模型类写法

ASP.NET Core 6 MVC + EF Core 用户区域权限模型实现方案

需求回顾

需要通过EF Core创建三个实体模型,对应以下数据库表结构以支持数据库迁移:

  • 用户主表(Users):存储用户基础信息
  • 区域主表(Areas):存储系统功能区域信息
  • 用户区域权限表(UserAreaAuthorizations):关联用户和区域,记录用户是否拥有该区域的访问权限

表结构示例:

-- USERS---
ID Name     
1  Tom
2  Jack
3  Smith

-- AREAS----
ID Name
10  LOGISTICS
20  FINANCE

-- USERAREAAUTHORIZATIONS------------
USERID  AREAID IsAuthorized
1       10     FALSE
1       20     TRUE
2       10     TRUE
2       20     FALSE
3       10     TRUE
3       20     TRUE

原代码问题分析

  • 字段类型错误:AppUsers类的Username字段定义为int,但实际需存储字符串类型的用户名(如Tom),类型不匹配
  • 导航属性不完整:AppUsersAuth缺少关联AppUsers的导航属性,EF无法正确识别用户与权限记录的一对多关系
  • 主键设计不合理:权限表使用单独的Id主键,不如用UserId+AreaId复合主键更符合业务唯一性规则
  • 属性命名混淆:AppUsers中的集合属性名AppUsersAuth与类名重复,易引发歧义
  • 反向导航缺失:AppAreas未添加关联权限记录的导航属性,无法从区域维度查询用户权限

修正后的模型代码

namespace App.Models
{
    // 用户实体
    public class AppUser
    {
        [Key]
        public int Id { get; set; }
        // 修正为字符串类型,对应示例中的Name字段
        public string Username { get; set; } = string.Empty;
        public string? FirstName { get; set; }
        public string? LastName { get; set; }

        // 关联用户的所有权限记录,重命名避免与类名混淆
        public ICollection<UserAreaAuthorization> UserAreaAuthorizations { get; set; } = new List<UserAreaAuthorization>();
    }

    // 用户区域权限实体
    public class UserAreaAuthorization
    {
        // 使用复合主键:一个用户对一个区域的权限唯一
        [Key, Column(Order = 0)]
        public int UserId { get; set; }
        [Key, Column(Order = 1)]
        public int AreaId { get; set; }

        public bool IsAuthorized { get; set; }

        // 关联用户实体的导航属性
        [ForeignKey(nameof(UserId))]
        public AppUser AppUser { get; set; } = null!;

        // 关联区域实体的导航属性
        [ForeignKey(nameof(AreaId))]
        public AppArea AppArea { get; set; } = null!;
    }

    // 区域实体
    public class AppArea
    {
        [Key]
        public int Id { get; set; }
        public string Name { get; set; } = string.Empty;

        // 反向导航:关联该区域的所有用户权限记录
        public ICollection<UserAreaAuthorization> UserAreaAuthorizations { get; set; } = new List<UserAreaAuthorization>();
    }
}

数据库上下文(DbContext)配置

在DbContext中添加DbSet,并可通过Fluent API明确配置关系(显式配置更清晰):

namespace App.Data
{
    public class AppDbContext : DbContext
    {
        public AppDbContext(DbContextOptions<AppDbContext> options) : base(options)
        {
        }

        public DbSet<AppUser> Users { get; set; }
        public DbSet<AppArea> Areas { get; set; }
        public DbSet<UserAreaAuthorization> UserAreaAuthorizations { get; set; }

        protected override void OnModelCreating(ModelBuilder modelBuilder)
        {
            // 配置权限表的复合主键
            modelBuilder.Entity<UserAreaAuthorization>()
                .HasKey(ua => new { ua.UserId, ua.AreaId });

            // 配置用户与权限的一对多关系
            modelBuilder.Entity<AppUser>()
                .HasMany(u => u.UserAreaAuthorizations)
                .WithOne(ua => ua.AppUser)
                .HasForeignKey(ua => ua.UserId)
                .OnDelete(DeleteBehavior.Cascade); // 删除用户时自动删除其权限记录

            // 配置区域与权限的一对多关系
            modelBuilder.Entity<AppArea>()
                .HasMany(a => a.UserAreaAuthorizations)
                .WithOne(ua => ua.AppArea)
                .HasForeignKey(ua => ua.AreaId)
                .OnDelete(DeleteBehavior.Restrict); // 删除区域时需先清理关联权限
        }
    }
}

控制器中的正确使用示例

若需查询用户权限并同时获取区域名称,需使用ThenInclude加载嵌套导航属性:

public class UserAuthorizationController : Controller
{
    private readonly AppDbContext _db;

    public UserAuthorizationController(AppDbContext db)
    {
        _db = db;
    }

    // 根据用户ID查询权限详情
    public IActionResult Index(int id)
    {
        var userWithAuth = _db.Users
            .Include(u => u.UserAreaAuthorizations)
                .ThenInclude(ua => ua.AppArea) // 加载权限关联的区域信息
            .FirstOrDefault(u => u.Id == id);

        return View(userWithAuth);
    }

    // 查询所有用户的权限列表
    public IActionResult List()
    {
        var allUsersWithAuth = _db.Users
            .Include(u => u.UserAreaAuthorizations)
                .ThenInclude(ua => ua.AppArea)
            .OrderBy(u => u.Username)
            .ToList();

        return View(allUsersWithAuth);
    }
}

数据库迁移步骤

  1. 打开包管理器控制台(PMC),执行命令创建迁移:
Add-Migration InitialCreate_UserAreaAuth
  1. 执行迁移更新数据库:
Update-Database

内容的提问来源于stack exchange,提问作者Joaquim Campos

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.16 04:34:58