Skip to content

实体与导航属性

实体基类

所有实体继承 EntityBase(或 EntityBaseWithUpdate),自动获得雪花 ID 和创建时间:

csharp
public abstract class EntityBase
{
    [Key]
    public long Id { get; set; } = IdGen.NextId();
    public DateTime CreatedTime { get; set; } = DateTime.Now;
}

public abstract class EntityBaseWithUpdate : EntityBase
{
    public DateTime? UpdatedTime { get; set; }
}

实体定义

csharp
[Table("sys_user")]
public class SysUser : EntityBase
{
    [MaxLength(50)]
    public string Username { get; set; } = default!;

    [MaxLength(1024)]
    public string Password { get; set; } = default!;

    [MaxLength(50)]
    public string? RealName { get; set; }

    public bool IsSuper { get; set; } = false;

    public ActiveStatus Status { get; set; } = ActiveStatus.正常;

    public DateTime? LastLoginTime { get; set; }
}

关键注解:

  • [Table("表名")] — 映射数据库表名
  • [MaxLength(n)] — 字符串长度约束
  • [Key] — 主键标注(基类已包含)

导航属性与 ForeignKey

Art Admin 数据库无外键约束(SQL 中不创建 FK),但在实体中使用 [ForeignKey] 注解来定义导航属性关系。

关联表示例

csharp
[Table("sys_user_role")]
public class SysUserRole
{
    public long UserId { get; set; }
    public long RoleId { get; set; }
    public DateTime CreatedTime { get; set; } = DateTime.Now;

    // 导航属性 — 通过 ForeignKey 关联
    [ForeignKey(nameof(UserId))]
    public SysUser SysUser { get; set; } = default!;

    [ForeignKey(nameof(RoleId))]
    public SysRole SysRole { get; set; } = default!;
}

Token 关联示例

csharp
[Table("token_access")]
public class TokenAccess
{
    [Key]
    public long Id { get; set; }

    public long RefreshTokenId { get; set; }
    public long UserId { get; set; }
    public TokenType Type { get; set; }
    public string Token { get; set; } = default!;
    public DateTime ExpirationTime { get; set; }

    // 导航属性 — 关联刷新令牌
    [ForeignKey(nameof(RefreshTokenId))]
    public TokenRefresh TokenRefresh { get; set; } = default!;
}

复合主键

关联表使用复合主键,在 DbContext.OnModelCreating 中配置:

csharp
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
    base.OnModelCreating(modelBuilder);

    modelBuilder.Entity<SysUserRole>()
        .HasKey(x => new { x.UserId, x.RoleId });

    modelBuilder.Entity<SysRoleMenu>()
        .HasKey(x => new { x.RoleId, x.MenuId });

    modelBuilder.Entity<SysRolePermission>()
        .HasKey(x => new { x.RoleId, x.PermissionId });
}

DbContext 注册

使用 DbContextPool 高性能连接池 + Snake Case 命名约定:

csharp
services.AddDbContextPool<ArtDbContext>((sp, options) =>
    options.UseMySql(connectionString, new MySqlServerVersion(new Version(8, 0, 0)))
        .UseSnakeCaseNamingConvention()
        .EnableSensitiveDataLogging(builder.Environment.IsDevelopment()));

Worker 中使用 IDbContextFactory(因为 Worker 不在请求作用域内):

csharp
services.AddDbContextFactory<ArtDbContext>((sp, options) =>
    options.UseMySql(connectionString, new MySqlServerVersion(new Version(8, 0, 0)))
        .UseSnakeCaseNamingConvention());

实体基类选择指南

基类包含字段适用场景
EntityBaseId + CreatedTime大多数业务实体
EntityBaseWithUpdate+ UpdatedTime需要记录更新时间
EntityBase<TKey>自定义主键类型 + CreatedTimestringGuid 主键
无基类完全自定义关联表、特殊表