从零开始Blazor Server(2)--整合数据库
开篇
上一篇文章我们留了个尾巴,没有把freesql整合进去,这篇文章我们来整合。
目前的思路呢,是做一个简单的四不像的RABC,也有用户、角色、
权限三部分。
但是其中每个用户只有一个角色,即用户和角色之间是一多关系。每个角色可以有多个权限,即权限跟角色之间是多多关系。
这样主要是想说一下freesql怎么做一多和多多关系。一个正常的RABC用户和角色之间也应该是多多,并且用户可能跟权限也可以有直接的联系。但是这个是一样的,只要权限列表拿到了,后面就随便怎么处理了。
建表
这次我们只建立四个表User、Role、Permission、RolePermisson。
采用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是自增的。同时还会自动生成CreateTime、UpdateTime、IsDeleted、Sort四个字段,这些都是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是用户角色一多关系的多的部分,我们只需要指定成ICollection,List也可以。使用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的模式,因为它应该是一个联合主键,不应该有个自增主键,并且也不需要那些CreateTime、UpdateTime、IsDeleted、Sort。但是这里为了省事,就直接用了,只是把主键类型改成了Guid,反正我们也不会使用这玩意来排序查询。也不会影响频繁删除的情况下可能出现的溢出问题。别的没什么好说的,就是两个属性
RoleId和PermissionId就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。
从零开始Blazor Server(2)--整合数据库的更多相关文章
- 从零开始Blazor Server(1)--项目搭建
项目介绍 本次项目准备搭建一个使用Furion框架,Blazor的UI使用BootstrapBlazor.数据库ORM使用Freesql的后台管理系统. 目前的规划是实现简单的注册,登录.增加管理员跟 ...
- 从零开始Blazor Server(15)--总结
我们用了14篇文章,基本上把一个后台管理系统需要的UI部分都说的差不多了.所以这套文章也该到了结束的时候了. 这里面有很多问题,比如我们直接使用UI来拉数据库信息而没有使用service,再比如我们大 ...
- 从零开始Blazor Server(3)--添加cookie授权
认证方式简述 Blazor Server微软官方还是推荐直接使用Cookie授权,因为本来Blazor Server就是前后端不分离的.不存在Cookie跨域等一系列问题. 只要不是使用SSO之类的统 ...
- 从零开始Blazor Server(4)--登录系统
说明 上一篇文章中我们添加了Cookie授权,可以跳转到登录页了.但是并没有完成登录,今天我们来完成它. 我们添加Cookie授权的时候也说了,这套跟MVC一模一样,所以我们登录也是跟MVC一模一样. ...
- 从零开始Blazor Server(5)--权限验证
序 之前我们一直使用的是微软自带的身份验证方式,即使用[Authorize]标签来做. 但是这种方式十分不灵活,微软推荐的方式是加Policy,但是这种方式对我们来说还是不够灵活. 所以本节我们用完全 ...
- 从零开始Blazor Server(6)--基于策略的权限验证
写这个的原因 现在BootstrapBlazor处于大更新时期,Menu组件要改为泛型模式. 本来我们的这一篇应该是把Layout改了,但是改Layout肯定要涉及到菜单,如果现在写了呢,就进入一个发 ...
- 从零开始Blazor Server(12)--编辑菜单
上个星期有点事,导致没法及时更新.现在我们继续更我们的从零开始系列. 这个系列也快要结束了,目前规划再有2-3篇,就结束了. 今天我们来说编辑菜单的问题,说实话菜单这种东西,你不更新代码加个页面,单独 ...
- 从零开始Blazor Server(7)--使用Furion权限验证
序 上面两篇我们讲了怎么用OnNavigateAsync来验证权限,又写了怎么用策略来验证权限. 其实我们既然集成了Fution,就可以用Furion带的方式来验证. 创建AdminHandler 我 ...
- 从零开始Blazor Server(8)--增加菜单以及调整位置
这篇干啥 这篇文章主要是把前面的一些东西稍微调整一下,使其更适合后面的内容. 主要是两个事,一个是把原来的PermissionEntity直接变成MenuEntity,直接让最后一级是菜单,这样后面就 ...
随机推荐
- Vue的vue-router基本使用
一.Vue-router是什么? Vue Router是Vue.js的路由管理器.和Vue.js的核心深度集成,是SPA单页应用的路径管理器,适合用于构建单页面应用.Vue的单页面应用是基于路由和组件 ...
- 从NSSRound#1学到了什么
sql_by_sql 二次注入: 更改密码的功能形如: update user set password='%s' where username='%s'; 的语句就可以存在二次注入,即假设有个adm ...
- Git命令行提交代码步骤
先进入对应的项目目录 1.拉取服务器代码,避免覆盖他人代码 git pull 2.查看当前项目中有哪些文件被修改过 git status 具体状态如下: 1:Untracked: 未跟踪,一般为新增文 ...
- 821. Shortest Distance to a Character - LeetCode
Question 821. Shortest Distance to a Character Solution 思路:遍历字符串S,遇到与字符C相等就分别向左/右计算其他字符与该字符的距离,如果其他字 ...
- 【单片机】CH32V103C8T6 ——窗口看门狗
本章教程通过串口调试助手打印显示程序运行状态,具体现象如下: 若计数器值在上窗口值和下窗口值0X40之间的时候,进行喂狗操作,计数器重新计数,程序正常运行,串口打印显示:The program run ...
- Python搜索书名获取整本资源_笔趣阁
前言 偶然一天把某项目文档传到手机上,用手机自带的阅读器方便随时拿出来查阅.看着我那好久没点开的阅读器,再看着书架上摆着几本不知道是多久之前导入的小说. 闭上眼,我仿佛看到那时候的自己.侧躺着缩在被窝 ...
- 关于『进击的Markdown』:第一弹
关于『进击的Markdown』:第一弹 建议缩放90%食用 比起隐蔽物下的狙击手,Markdown更像冲锋陷阵的阵头兵 简单.粗暴.直接.而且好上手 各位晚上好! 早饭吃了吗您 我 今 天 没 吃 M ...
- Go微服务框架go-kratos实战05:分布式链路追踪 OpenTelemetry 使用
一.分布式链路追踪发展简介 1.1 分布式链路追踪介绍 关于分布式链路追踪的介绍,可以查看我前面的文章 微服务架构学习与思考(09):分布式链路追踪系统-dapper论文学习(https://www. ...
- 2021.04.03【NOIP提高B组】模拟 总结
T1 题目大意:求最小的 \(n\in[0,lim]\) 使得区间 \([L,R]\) 在线段树建树 \(build(0,n)\) 的区间内 考场时想到了正解,结果推式子退错了... 其实就是从下往上 ...
- 借助SpotBugs将程序错误扼杀在摇篮中
背景 最近一年多在一家toB业务的公司,部门主要做的是建筑行业的招投标业务信息化,希望借助软件来达到"阳光.降本.提效"的目的,我刚入职时大概30多家客户,截止现在已经超过100家 ...