上一篇文章我們留了個尾巴,沒有把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
的包,沒有掛進程式裡,現在我們把它弄到程式裡去。
首先我們把連線字串整到組態檔裡去,比如我放在
"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。