ASP.NET Core搭建多层网站架构【4.2-网站数据库实体设计及映射配置】

♀尐吖头ヾ 提交于 2020-01-28 21:09:34

2020/01/28, ASP.NET Core 3.1, VS2019, EntityFrameworkCore 3.1

摘要:基于ASP.NET Core 3.1 WebApi搭建后端多层网站架构【4.2-网站数据库实体设计及映射配置】
网站数据库实体设计,使用EntityFrameworkCore 3.1 FluentAPI映射配置实体

文章目录
此分支项目代码
本章节介绍后台管理的网站数据库实体设计

需求分析

首先要实现的功能有用户登录、角色管理、日志记录
大概有四张表:用户表、密码表、角色表、日志表
日志表:

用户表:

密码表:

角色表:

好像博客园md不支持表格功能?所以只能截图展示,excel表格上传至项目docs文件夹中

字段设计说明

  • 日志表主键Id是数据库自增的,也就是在向数据库插入日志时,不用管Id,往里写入就行
  • 用户表、角色表的Id都是long类型的,也就是使用雪花算法生成的Id
  • 密码表的主键是Account,UserId是用户表外键
  • 用户表和角色表拥有StatusCode、Creator、CreateTime、Modifier、ModifyTime,标明该记录的状态、创建时间等信息

创建实体类

MS.Entities类库中添加Core文件夹,在Core文件夹中添加IEntity.cs类:

using System;

namespace MS.Entities.Core
{
    //没有Id主键的实体继承这个
    public interface IEntity
    {
    }
    //有Id主键的实体继承这个
    public abstract class BaseEntity : IEntity
    {
        public long Id { get; set; }
        public StatusCode StatusCode { get; set; }
        public long? Creator { get; set; }
        public DateTime? CreateTime { get; set; }
        public long? Modifier { get; set; }
        public DateTime? ModifyTime { get; set; }
    }
}

在Core中新建StatusCode.cs枚举:

using System.ComponentModel;

namespace MS.Entities.Core
{
    public enum StatusCode
    {
        [Description("已删除")]
        Deleted = -1,//软删除,已删除的无法恢复,无法看见,暂未使用
        [Description("生效")]
        Enable = 0,
        [Description("失效")]
        Disable = 1//失效的还可以改为生效
    }
}

日志表

MS.Entities类库中添加Logrecord.cs类:

using MS.Entities.Core;
using System;

namespace MS.Entities
{
    public class Logrecord : IEntity
    {
        public int Id { get; set; }
        public DateTime LogDate { get; set; }
        public string LogLevel { get; set; }
        public string Logger { get; set; }
        public string Message { get; set; }
        public string Exception { get; set; }
        public string MachineName { get; set; }
        public string MachineIp { get; set; }
        public string NetRequestMethod { get; set; }
        public string NetRequestUrl { get; set; }
        public string NetUserIsauthenticated { get; set; }
        public string NetUserAuthtype { get; set; }
        public string NetUserIdentity { get; set; }
    }
}

角色表

MS.Entities类库中添加Role.cs类:

using MS.Entities.Core;

namespace MS.Entities
{
    public class Role : BaseEntity
    {
        public string Name { get; set; }
        public string DisplayName { get; set; }
        public string Remark { get; set; } 
    }
}

用户表

MS.Entities类库中添加User.cs类:

using MS.Entities.Core;

namespace MS.Entities
{
    public class User : BaseEntity
    {
        public string Account { get; set; }
        public string Name { get; set; }
        public string Email { get; set; }
        public string Phone { get; set; }
        public long RoleId { get; set; } 

        public Role Role { get; set; }
    }
}

密码表

MS.Entities类库中添加UserLogin.cs类:

using MS.Entities.Core;
using System;

namespace MS.Entities
{
    public class UserLogin : IEntity
    {
        public long UserId { get; set; }
        public string Account { get; set; }
        public string HashedPassword { get; set; }
        public DateTime? LastLoginTime { get; set; }
        public int AccessFailedCount { get; set; }
        public bool IsLocked { get; set; }
        public DateTime? LockedTime { get; set; }

        public User User { get; set; }
    }
}

至此,实体类都已完成设计
项目完成后,如下图

创建映射配置

MS.DbContexts类库添加包引用:

<ItemGroup>
  <PackageReference Include="Microsoft.Extensions.Logging.Console" Version="3.1.1" />
  <PackageReference Include="Microsoft.Extensions.Logging.Debug" Version="3.1.1" />
</ItemGroup>

这两个包给DbContext扩展日志记录,比如最终EFCore生成的sql语句想查看可以通过这个办法,后文会提到

MS.DbContexts类库中引用MS.EntitiesMS.UnitOfWork类库
MS.DbContexts类库中添加Mappings文件夹,在该文件夹中添加 LogrecordMap.csRoleMap.csUserLoginMap.csUserMap.cs

LogrecordMap.cs

using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Metadata.Builders;
using MS.Entities;

namespace EvMS.DbContexts
{
    public class LogrecordMap : IEntityTypeConfiguration<Logrecord>
    {
        public void Configure(EntityTypeBuilder<Logrecord> builder)
        {
            builder.ToTable("TblLogrecords");
            builder.HasKey(c => c.Id);//自增主键
            builder.Property(c => c.LogDate).IsRequired();
            builder.Property(u => u.LogLevel).IsRequired().HasMaxLength(50);
            builder.Property(u => u.Logger).IsRequired().HasMaxLength(256);
            builder.Property(u => u.Message);
            builder.Property(u => u.Exception);
            builder.Property(u => u.MachineName).HasMaxLength(50);
            builder.Property(u => u.MachineIp).HasMaxLength(50);
            builder.Property(u => u.NetRequestMethod).HasMaxLength(10);
            builder.Property(u => u.NetRequestUrl).HasMaxLength(500);
            builder.Property(u => u.NetUserIsauthenticated).HasMaxLength(10);
            builder.Property(u => u.NetUserAuthtype).HasMaxLength(50);
            builder.Property(u => u.NetUserIdentity).HasMaxLength(50);
        }
    }
}

RoleMap.cs

using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Metadata.Builders;
using MS.Entities;

namespace EvMS.DbContexts
{
    public class RoleMap : IEntityTypeConfiguration<Role>
    {
        public void Configure(EntityTypeBuilder<Role> builder)
        {
            builder.ToTable("TblRoles");
            builder.HasKey(c => c.Id);
            builder.Property(c => c.Id).ValueGeneratedNever();
            builder.HasIndex(c => c.Name).IsUnique();//指定索引,不能重复
            builder.Property(c => c.Name).IsRequired().HasMaxLength(16);
            builder.Property(c => c.DisplayName).IsRequired().HasMaxLength(50);
            builder.Property(c => c.Remark).HasMaxLength(4000);
            builder.Property(c => c.Creator).IsRequired();
            builder.Property(c => c.CreateTime).IsRequired();
            builder.Property(c => c.Modifier);
            builder.Property(c => c.ModifyTime);
            //builder.HasQueryFilter(b => b.StatusCode != StatusCode.Deleted);//默认不查询软删除数据
        }
    }
}

UserLoginMap.cs

using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Metadata.Builders;
using MS.Entities;

namespace EvMS.DbContexts
{
    public class UserLoginMap : IEntityTypeConfiguration<UserLogin>
    {
        public void Configure(EntityTypeBuilder<UserLogin> builder)
        {
            builder.ToTable("TblUserLogins");
            builder.HasKey(c => c.Account);
            //builder.Property(c => c.UserId).ValueGeneratedNever();
            builder.Property(c => c.Account).IsRequired().HasMaxLength(20);
            builder.Property(c => c.HashedPassword).IsRequired().HasMaxLength(256);
            builder.Property(c => c.LastLoginTime);
            builder.Property(c => c.AccessFailedCount).IsRequired().HasDefaultValue(0);
            builder.Property(c => c.IsLocked).IsRequired();
            builder.Property(c => c.LockedTime);
            builder.HasOne(c => c.User);
        }
    }
}

UserMap.cs

using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Metadata.Builders;
using MS.Entities;
using MS.Entities.Core;

namespace EvMS.DbContexts
{
    public class UserMap : IEntityTypeConfiguration<User>
    {
        public void Configure(EntityTypeBuilder<User> builder)
        {
            builder.ToTable("TblUsers");
            builder.HasKey(c => c.Id);
            builder.Property(c => c.Id).ValueGeneratedNever();
            builder.HasIndex(c => c.Account).IsUnique();//指定索引
            builder.Property(c => c.Account).IsRequired().HasMaxLength(16);
            builder.Property(c => c.Name).IsRequired().HasMaxLength(50);
            builder.Property(c => c.Email).HasMaxLength(100);
            builder.Property(c => c.Phone).HasMaxLength(25);
            builder.Property(c => c.RoleId).IsRequired();
            builder.Property(c => c.StatusCode).IsRequired().HasDefaultValue(StatusCode.Enable);
            builder.Property(c => c.Creator).IsRequired();
            builder.Property(c => c.CreateTime).IsRequired();
            builder.Property(c => c.Modifier);
            builder.Property(c => c.ModifyTime);

            builder.HasOne(c => c.Role);
            //builder.HasQueryFilter(b => b.StatusCode != StatusCode.Deleted);//默认不查询软删除数据
        }
    }
}
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!