11

从零开始Blazor Server(2)--整合数据库 - jvx

 2 years ago
source link: https://www.cnblogs.com/j4587698/p/16527556.html
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client

从零开始Blazor Server(2)--整合数据库

上一篇文章我们留了个尾巴,没有把freesql整合进去,这篇文章我们来整合。

目前的思路呢,是做一个简单的四不像的RABC,也有用户、角色、

权限三部分。

但是其中每个用户只有一个角色,即用户和角色之间是一多关系。每个角色可以有多个权限,即权限跟角色之间是多多关系。

这样主要是想说一下freesql怎么做一多和多多关系。一个正常的RABC用户和角色之间也应该是多多,并且用户可能跟权限也可以有直接的联系。但是这个是一样的,只要权限列表拿到了,后面就随便怎么处理了。

这次我们只建立四个表UserRolePermissionRolePermisson

采用CodeFirst的方式,优先建立Entity,使用Freesql的数据库同步功能生成表结构。

User表:

[Description("用户信息表")]
public class UserEntity : BaseEntity<UserEntity, int>
{
    [Description("用户名")]
    public string? UserName { get; set; }

    [Description("密码")]
    public string? Password { get; set; }

    [Description("用户姓名")]
    public string? Name { get; set; }

    [Description("角色Id")]
    public int RoleId { get; set; }

    [Description("角色")]
    [Navigate(nameof(RoleId))]
    public RoleEntity? Role { get; set; }
}

借着User表解释一下。

  • 继承了BaseEntity<UserEntity, int>以后,会添加一个int类型的Id,这个Id是自增的。同时还会自动生成CreateTimeUpdateTimeIsDeletedSort四个字段,这些都是BaseEntity自带的功能,使用BaseEntity在查询的时候会自动携带IsDeleted标识,让我们可以轻松软删除。

  • Description标签在Freesql里可以自动生成注释,由于sqlite不支持注释,所以这里没有用,单纯是作为注释来使用。

  • FreeSql的一多关系,这里是一的部分,使用起来很简单,有一个RoleId,然后定义一个RoleEntity,标签里用Navigate指定通过RoleId来查询就行了。

Role表:

[Description("角色表")]
public class RoleEntity : BaseEntity<RoleEntity, int>
{
    [Description("角色名称")]
    public string? Name { get; set; }

    [Description("用户")]
    [Navigate(nameof(UserEntity.RoleId))]
    public virtual ICollection<UserEntity>? Users { get; set; }

    [Description("权限")]
    [Navigate(ManyToMany = typeof(RolePermissionEntity))]
    public virtual ICollection<PermissionEntity>? Permissions { get; set; }
}
  • Users是用户角色一多关系的多的部分,我们只需要指定成ICollectionList也可以。使用Navigate指定关联的名字为RoleId就可以了。这里需要注意的是一定是关联RoleId不是User表的Id,关联错了的话这里的关系就乱掉了。

  • Permissions是角色权限多多关系的处理部分,属性写起来跟一多关系一样,但是Navigate标签里不再是绑定一个字符串了,而是用ManyToMany指定一个type,这个type是我们多多关系的中间表。这个表我们下面讲。

RolePermission

[Description("角色权限多多关系表")]
public class RolePermissionEntity : BaseEntity<RolePermissionEntity, Guid>
{
    [Description("角色Id")]
    public int RoleId { get; set; }

    [Description("角色")]
    [Navigate(nameof(RoleId))]
    public RoleEntity? Role { get; set; }

    [Description("权限Id")]
    public int PermissionId { get; set; }

    [Description("权限")]
    [Navigate(nameof(PermissionId))]
    public PermissionEntity? Permission { get; set; }
}
  • 严格来说,这个表不应该使用BaseEntity的模式,因为它应该是一个联合主键,不应该有个自增主键,并且也不需要那些CreateTimeUpdateTimeIsDeletedSort。但是这里为了省事,就直接用了,只是把主键类型改成了Guid,反正我们也不会使用这玩意来排序查询。也不会影响频繁删除的情况下可能出现的溢出问题。

  • 别的没什么好说的,就是两个属性RoleIdPermissionId就i行了,如果用不着它,那Entity都可以不加。

Permission

[Description("权限表")]
public class PermissionEntity: BaseEntity<PermissionEntity, int>
{
    [Description("权限名")]
    public string? Name { get; set; }

    [Description("对应页面Url")]
    public string? Url { get; set; }
    
    [Description("角色")]
    [Navigate(ManyToMany = typeof(RolePermissionEntity))]
    public virtual ICollection<RoleEntity>? Roles { get; set; }
}

这个表没什么好说的了,就是一个多多关系,跟Role的是一样的。

添加FreeSql

之前我们只是添加了FreeSql的包,没有挂进程序里,现在我们把它弄到程序里去。

首先我们把连接字符串整到配置文件里去,比如我放在

"Db": {
    "ConnString": "Data Source=|DataDirectory|\\document.db; Pooling=true;Min Pool Size=1"
  },

这样我们就可以在任何位置 用var conn = Furion.App.Configuration["Db:ConnString"];获取到连接字符串了。

然后我们需要创建一个freesql的实例

        var freeSql = new FreeSqlBuilder()
            .UseAutoSyncStructure(Furion.App.WebHostEnvironment.IsDevelopment())
            .UseConnectionString(DataType.Sqlite, conn)
            .Build();

这里的UseAutoSyncStructure是是否开启自动迁移,如果开启了,freesql用的时候发现没有表或者表结构不对,就自动迁移表结构,这个东西生产上不建议用,所以我们就只有在Development的时候使用。

然后我们的Entity都有Entity后缀,这个放到数据库里不好看,我们就把它给去掉

freeSql.Aop.ConfigEntity += (s, e) =>
        {
            e.ModifyResult.Name = e.EntityType.Name.Replace("Entity", "");
        };

另外如果你需要加前缀,或者改大小写,改下划线都可以在这里金信处理。

因为我们使用的是BaseEntity模式,所以这里需要初始化

BaseEntity.Initialization(freeSql, null);

最后我们还需要添加一些默认的用户,角色,权限

        if (!UserEntity.Where(x => x.UserName == "Admin").Any())
        {
            UserEntity user = new UserEntity()
            {
                UserName = "Admin",
                Password = MD5Encryption.Encrypt("Admin"),
                Name = "张三"
            };
            user.Save();
            

            PermissionEntity homePermission = new PermissionEntity()
            {
                Name = "首页",
                Url = "/"
            };
            homePermission.Save();
            
            PermissionEntity userPermission = new PermissionEntity()
            {
                Name = "用户管理",
                Url = "/User"
            };
            userPermission.Save();
            
            RoleEntity role = new RoleEntity()
            {
                Name = "管理员",
                Users = new List<UserEntity>() { user },
                Permissions = new List<PermissionEntity>(){homePermission, userPermission}
            };
            role.Save().SaveMany(nameof(RoleEntity.Users));
            role.SaveMany(nameof(RoleEntity.Permissions));
        }

这里需要注意,如果有多表的部分需要连其他的表一起更新,那就需要主动调用SaveMany方法,如果不调用,那么不会自动更新。

源码在github:https://github.com/j4587698/BlazorLearn,分支lesson2。


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK