开篇

上一篇文章我们留了个尾巴,没有把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。

从零开始Blazor Server(2)--整合数据库的更多相关文章

  1. 从零开始Blazor Server(1)--项目搭建

    项目介绍 本次项目准备搭建一个使用Furion框架,Blazor的UI使用BootstrapBlazor.数据库ORM使用Freesql的后台管理系统. 目前的规划是实现简单的注册,登录.增加管理员跟 ...

  2. 从零开始Blazor Server(15)--总结

    我们用了14篇文章,基本上把一个后台管理系统需要的UI部分都说的差不多了.所以这套文章也该到了结束的时候了. 这里面有很多问题,比如我们直接使用UI来拉数据库信息而没有使用service,再比如我们大 ...

  3. 从零开始Blazor Server(3)--添加cookie授权

    认证方式简述 Blazor Server微软官方还是推荐直接使用Cookie授权,因为本来Blazor Server就是前后端不分离的.不存在Cookie跨域等一系列问题. 只要不是使用SSO之类的统 ...

  4. 从零开始Blazor Server(4)--登录系统

    说明 上一篇文章中我们添加了Cookie授权,可以跳转到登录页了.但是并没有完成登录,今天我们来完成它. 我们添加Cookie授权的时候也说了,这套跟MVC一模一样,所以我们登录也是跟MVC一模一样. ...

  5. 从零开始Blazor Server(5)--权限验证

    序 之前我们一直使用的是微软自带的身份验证方式,即使用[Authorize]标签来做. 但是这种方式十分不灵活,微软推荐的方式是加Policy,但是这种方式对我们来说还是不够灵活. 所以本节我们用完全 ...

  6. 从零开始Blazor Server(6)--基于策略的权限验证

    写这个的原因 现在BootstrapBlazor处于大更新时期,Menu组件要改为泛型模式. 本来我们的这一篇应该是把Layout改了,但是改Layout肯定要涉及到菜单,如果现在写了呢,就进入一个发 ...

  7. 从零开始Blazor Server(12)--编辑菜单

    上个星期有点事,导致没法及时更新.现在我们继续更我们的从零开始系列. 这个系列也快要结束了,目前规划再有2-3篇,就结束了. 今天我们来说编辑菜单的问题,说实话菜单这种东西,你不更新代码加个页面,单独 ...

  8. 从零开始Blazor Server(7)--使用Furion权限验证

    序 上面两篇我们讲了怎么用OnNavigateAsync来验证权限,又写了怎么用策略来验证权限. 其实我们既然集成了Fution,就可以用Furion带的方式来验证. 创建AdminHandler 我 ...

  9. 从零开始Blazor Server(8)--增加菜单以及调整位置

    这篇干啥 这篇文章主要是把前面的一些东西稍微调整一下,使其更适合后面的内容. 主要是两个事,一个是把原来的PermissionEntity直接变成MenuEntity,直接让最后一级是菜单,这样后面就 ...

随机推荐

  1. Python生成GIF动态图

    python生成摸头GIF 本篇教程演示了如何使用python的PIL库生成GIF图片 源码已经贴在文中,自行取用 效果演示 运行代码,会让你选择要制作的图片 运行完成后,会在同路径下生成dem.gi ...

  2. 太极限了,JDK的这个BUG都能被我踩到

    hello,大家好呀,我是小楼. 之前遇到个文件监听变更的问题,刚好这周末有空研究了一番,整理出来分享给大家. 从一次故障说起 我们还是从故障说起,这样更加贴近实际,也能让大家更快速理解背景. 有一个 ...

  3. 手动验证 TLS 证书

    证书结构 我们现在使用的 TLS 证书的标准是 X.509,版本号为 V3.版本号可从证书的 Version 字段看到. 根据 RFC 3280 定义的证书结构,证书由三个部分组成: 证书主体(TBS ...

  4. jenkins插件Role-based添加账号后显示红色"No type prefix"

    jenkins插件Role-based添加账号save后,前面显示红色"No type prefix",不影响使用. 查了下原因,网上很少正解,我这里记录下正确的方法: 添加用户: ...

  5. Vue的Vuex的使用

    一.Vuex是什么? 1:Vuex是一个专为vue.js应用程序开发的状态管理模式,核心就是一个store仓库,采用集中式存储管理应用的所有组件的状态,并以相应的规则保证状态以一种可预测的方式发生变化 ...

  6. 大陆出境海缆TPE APCN NCP APG简介

    目前我国的登陆站主要设立在三个城市 山东 山东青岛登陆站(隶属中国联通) EAC-C2C TPE(美国方向) 上海 上海崇明登陆站(隶属中国电信) APCN2(亚太) NCP(长线--美国,新建,亚太 ...

  7. 使用python获取交换机syslog日志并使用jQuery在html上展示

    需求 现网有部分pop点独立于海外,无法发送日志给内网日志服务器,同时最近网内有比较重要割接,所以临时写一个脚本来展示网内日志 思路 使用socket接收syslog数据,udp 514,数据部分格式 ...

  8. 图文详解 HDFS 的工作机制及其原理

    大家好,我是大D. 今天开始给大家分享关于大数据入门技术栈--Hadoop的学习内容. 初识 Hadoop 为了解决大数据中海量数据的存储与计算问题,Hadoop 提供了一套分布式系统基础架构,核心内 ...

  9. How to fetch data with React Hooks

    Where can I make API call with hooks in react? Async useEffect is pretty much unreadable How to fetc ...

  10. 好客租房30-事件绑定this指向(箭头函数)

    1箭头函数 利用箭头函数自身不绑定this的特点 //导入react     import React from 'react'           import ReactDOM from 'rea ...