EntityFramework Core使用PostgreSQL
0 Asp.Net Core 項目實戰之權限管理系統(0) 無中生有
1 Asp.Net Core 項目實戰之權限管理系統(1) 使用AdminLTE搭建前端
2 Asp.Net Core 項目實戰之權限管理系統(2) 功能及實體設計
3 Asp.Net Core 項目實戰之權限管理系統(3) 通過EntityFramework Core使用PostgreSQL
4 Asp.Net Core 項目實戰之權限管理系統(4) 用戶登錄
0 PostgreSQL安裝及配置
0.0 PostgreSQL簡介
既然Asp.Net Core最大的特性就是跨平台,就搭配使用一個可以跨平台的數據庫。PostgreSQL是一個功能強大的開源數據庫系統。經過長達15年以上的積極開發和不斷改進,PostgreSQL已在可靠性、穩定性、數據一致性等獲得了業內極高的聲譽。目前PostgreSQL可以運行在所有主流操作系統上,包括Linux、Unix(AIX、BSD、HP-UX、SGI IRIX、Mac OS X、Solaris和Tru64)和Windows。PostgreSQL是完全的事務安全性數據庫,完整地支持外鍵、聯合、視圖、觸發器和存儲過程(並支持多種語言開發存儲過程)。它支持了大多數的SQL:2008標准的數據類型,包括整型、數值值、布爾型、字節型、字符型、日期型、時間間隔型和時間型,它也支持存儲二進制的大對像,包括圖片、聲音和視頻。PostgreSQL對很多高級開發語言有原生的編程接口,如C/C++、Java、.Net、Perl、Python、Ruby、Tcl 和ODBC以及其他語言等,也包含各種文檔。
0.1 PostgreSQL安裝及配置
自行去PostgreSQL官網下載符合你自己系統的版本,開始安裝,從我自己的安裝體驗來看,沒什么需要特別注意的地方,只需要按照提示一步步安裝即可,在最后的時候根據需要選擇以下語言,設置超級用戶角色postgres的登錄密碼即可。
創建一個系統使用的角色
打開安裝好的PostgreSQL數據庫,輸入密碼進入管理界面。右鍵“登錄角色”,創建一個名稱為“fonour”的角色,在“角色權限”頁簽中把所有能能勾選的功能都勾選上。
右鍵PostgreSQL服務器,選擇斷開服務器。接着右鍵,單擊“屬性”菜單,在彈出窗口的用戶名出輸入剛才新建的“fonour”角色,輸入密碼並勾選記住密碼。確定,連接即可。
1 使用EntityFrameworkCore的CodeFirst方式創建數據庫
1.0 在Fonour.EntityFrameworkCore項目中創建DbContext
由於EF Core跟PostgreSQL都需要現學現用,EF Core的使用跟EF6.0還是有很多不同的,在使用的過程中遇到了不少的問題,尤其是針對PostgreSQL使用Guid類型的主鍵,后面會把這些坑做一個簡單的記錄。
0 添加相關依賴項
需要添加的相關依賴及說明如下:
- Npgsql.EntityFrameworkCore.PostgreSQL
PostgreSQL數據提供的支持EF Core的基礎類庫,是通過EF Core使用PostgreSQL數據庫的根本。
- Npgsql.EntityFrameworkCore.PostgreSQL.Design
使用Guid(對應Postgre數據的類型為uuid)類型的主鍵必須,int/long類型的主鍵不添加也沒問題。
- Microsoft.EntityFrameworkCore.Tools
EF Core工具,CodeFirst數據庫遷移相關操作必須。
- Fonour.Domain
我們自己創建的一個類庫項目,其中包含了組織機構、功能、角色、用戶等實體的定義。
添加相關引用依賴的方式有多種,可以通過NuGet程序包管理器控制台的Install-Packege命令
PM> Install-Package Npgsql.EntityFrameworkCore.PostgreSQL PM> Install-Package Npgsql.EntityFrameworkCore.PostgreSQL.Design PM> Install-Package Microsoft.EntityFrameworkCore.Tools
或者直接在NuGet程序包管理器中搜索相關類庫,進行安裝
最直接的方法是直接修改project.json配置文件,project.json配置文件最終修改后內容如下。
{
"version": "1.0.0-*",
"dependencies": {
"Fonour.Domain": "1.0.0-0",
"Microsoft.EntityFrameworkCore.Tools": "1.0.0-preview2-final",
"NETStandard.Library": "1.6.0",
"Npgsql.EntityFrameworkCore.PostgreSQL": "1.0.1",
"Npgsql.EntityFrameworkCore.PostgreSQL.Design": "1.0.1"
},
"frameworks": {
"netcoreapp1.0": {
"imports": [
"dotnet5.6",
"portable-net45+win8"
]
}
},
"tools": {
"Microsoft.EntityFrameworkCore.Tools": {
"version": "1.0.0-preview2-final",
"imports": [
"portable-net45+win8+dnxcore50",
"portable-net45+win8"
]
}
}
}
注意,frameworks部分,如果默認是netstandard1.6框架,必須進行修改,否則會提示不支持相關依賴項。
1 創建DbContext
根據EF Core對多對多關聯關系的要求,增加了UserRole、RoleMenu兩個關聯關系實體,同時對原有實體進行了調整。
public class UserRole
{
public Guid UserId { get; set; }
public User User { get; set; }
public Guid RoleId { get; set; }
public Role Role { get; set; }
}
public class RoleMenu
{
public Guid RoleId { get; set; }
public Role Role { get; set; }
public Guid MenuId { get; set; }
public Menu Menu { get; set; }
}
在Fonour.EntityFrameworkCore項目下新建一個數據上下文操作類,命名為“FonourDBContext”,其中增加權限管理系統相關實體的DbSet的定義。最終代碼如下:
public class FonourDbContext : DbContext
{
public FonourDbContext(DbContextOptions<FonourDbContext> options) : base(options)
{
}
public DbSet<Department> Departments { get; set; }
public DbSet<Menu> Menus { get; set; }
public DbSet<Role> Roles { get; set; }
public DbSet<User> Users { get; set; }
public DbSet<UserRole> UserRoles { get; set; }
public DbSet<RoleMenu> RoleMenus { get; set; }
protected override void OnModelCreating(ModelBuilder builder)
{
//UserRole關聯配置
builder.Entity<UserRole>()
.HasKey(ur => new { ur.UserId, ur.RoleId });
//RoleMenu關聯配置
builder.Entity<RoleMenu>()
.HasKey(rm => new { rm.RoleId, rm.MenuId });
builder.Entity<RoleMenu>()
.HasOne(rm => rm.Role)
.WithMany(r => r.RoleMenus)
.HasForeignKey(rm => rm.RoleId).HasForeignKey(rm => rm.MenuId);
//啟用Guid主鍵類型擴展
builder.HasPostgresExtension("uuid-ossp");
base.OnModelCreating(builder);
}
}
1.1 在Fonour.MVC項目中進行數據庫連接相關配置
0 添加相關依賴項
在Asp.Net Core中,使用json格式的配置文件進行系統相關參數的配置,將相關配置文件通過ConfigurationBuilder進行統一管理,得到IConfigurationRoot的配置實例,獲取相關配置文件配置節點的信息。想要使用配置文件相關服務,需要添加一下依賴。
- Microsoft.Extensions.Configuration
- Microsoft.Extensions.Configuration.FileExtensions
- Microsoft.Extensions.Configuration.Json
還需要添加對Fonour.EntityFrameworkCore項目的引用。
最終Fonour.MVC項目的project.json文件配置如下:
{
"dependencies": {
"Microsoft.NETCore.App": "1.0.1",
"Microsoft.AspNetCore.Diagnostics": "1.0.0",
"Microsoft.AspNetCore.Server.IISIntegration": "1.0.0",
"Microsoft.AspNetCore.Server.Kestrel": "1.0.1",
"Microsoft.Extensions.Logging.Console": "1.0.0",
"Microsoft.AspNetCore.Mvc": "1.0.1",
"Microsoft.AspNetCore.StaticFiles": "1.0.0",
"Microsoft.Extensions.Configuration": "1.0.0",
"Microsoft.Extensions.Configuration.FileExtensions": "1.0.0",
"Microsoft.Extensions.Configuration.Json": "1.0.0",
"Fonour.EntityFrameworkCore": "1.0.0-*"
},
"tools": {
"Microsoft.AspNetCore.Server.IISIntegration.Tools": "1.0.0-preview2-final"
},
"frameworks": {
"netcoreapp1.0": {
"imports": [
"dotnet5.6",
"portable-net45+win8"
]
}
},
"buildOptions": {
"emitEntryPoint": true,
"preserveCompilationContext": true
},
"runtimeOptions": {
"configProperties": {
"System.GC.Server": true
}
},
"publishOptions": {
"include": [
"wwwroot",
"web.config"
]
},
"scripts": {
"postpublish": [ "dotnet publish-iis --publish-folder %publish:OutputPath% --framework %publish:FullTargetFramework%" ]
},
"runtimes": {
"win10-x64": {}
}
}
1 增加appsettings.json配置文件
右鍵Fonour.MVC項目,新增一個Asp.Net配置文件類型,名稱為appsettings.json的配置文件。
appsettings.json文件目前主要內容為定義數據庫連接字符串,內容如下:
{
"ConnectionStrings": {
"Default": "User ID=fonour;Password=123456;Host=localhost;Port=5432;Database=Fonour;Pooling=true;"
}
}
2 啟用數據庫連接
首先在Startup.cs中定義一個IConfigurationRoot的屬性,然后在系統啟動類Startup.cs的構造函數中,對配置文件進行管理。
public IConfigurationRoot Configuration { get; }
public Startup(IHostingEnvironment env)
{
var builder = new ConfigurationBuilder()
.SetBasePath(env.ContentRootPath)
.AddJsonFile("appsettings.json", optional: true, reloadOnChange: true)
.AddJsonFile($"appsettings.{env.EnvironmentName}.json", optional: true);
builder.AddEnvironmentVariables();
Configuration = builder.Build();
}
在ConfigureServices方法中獲取數據庫連接字符串,並添加數據庫連接服務。
public void ConfigureServices(IServiceCollection services)
{
//獲取數據庫連接字符串
var sqlConnectionString = Configuration.GetConnectionString("Default");
//添加數據上下文
services.AddDbContext<FonourDbContext>(options =>
options.UseNpgsql(sqlConnectionString)
);
services.AddMvc();
}
1.2 使用CodeFirst數據庫遷移命令創建數據庫
在EntityFrameworkCore中數據庫遷移有兩種方式。
0 使用命令行工具
在應用程序根目錄按住shift鍵同時單擊鼠標右鍵,選擇“在此處打開命令窗口”,輸入數據庫遷移的命令
dotnet ef migrations add Init dotnet ef database update
1 使用程序包管理器控制台
在程序包管理器控制台中默認項目選擇Fonour.EntityFrameworkCore,輸入以下命令,自動創建數據庫遷移文件。
Add-Migration Init
注意,一定要將Fonour.MVC設置為啟動項目。
執行完成后,項目中增加了數據庫遷移文件。
輸入以下命令,進行數據庫更新操作。
Update-Database
提示更新完成后,查看我們的數據庫,會發現數據庫及數據庫表已經創建完成。
2 數據初始化
為保證系統正常運行,我們需要對系統進行數據初始化,要初始化的數據包括一下內容:
- 用戶表插入一條用戶名為admin的超級管理員用戶信息
- 功能菜單表增加組織機構管理、角色管理、用戶管理、功能管理四條基本數據。
- 組織機構表插入一條組織機構信息(主要是因為用戶表存在一個DepartmentId的外鍵)
在Fonour.EntityFrameworkCore項目中增加一個新的數據初始化類,命名為SeedData.cs,修改內容如下:
public static class SeedData
{
public static void Initialize(IServicePr
{
using (var context = new FonourDbCon
{
if (context.Users.Any())
{
return; // 已經初始化過數據
}
Guid departmentId = Guid.NewGuid
//增加一個部門
context.Departments.Add(
new Department
{
Id = departmentId,
Name = "Fonour集團總部",
ParentId = Guid.Empty
}
);
//增加一個超級管理員用戶
context.Users.Add(
new User
{
UserName = "admin",
Password = "123456", //
Name = "超級管理員",
DepartmentId = departme
}
);
//增加四個基本功能菜單
context.Menus.AddRange(
new Menu
{
Name = "組織機構管理",
Code = "Department",
SerialNumber = 0,
ParentId = Guid.Empty,
Icon = "fa fa-link"
},
new Menu
{
Name = "角色管理",
Code = "Role",
SerialNumber = 1,
ParentId = Guid.Empty,
Icon = "fa fa-link"
},
new Menu
{
Name = "用戶管理",
Code = "User",
SerialNumber = 2,
ParentId = Guid.Empty,
Icon = "fa fa-link"
},
new Menu
{
Name = "功能管理",
Code = "Department",
SerialNumber = 3,
ParentId = Guid.Empty,
Icon = "fa fa-link"
}
);
context.SaveChanges();
}
}
}
在Fonour.MVC項目的Startup.cs中Configure方法最后增加數據初始化的操作。
public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
{
loggerFactory.AddConsole();
if (env.IsDevelopment())
{
//開發環境異常處理
app.UseDeveloperExceptionPage();
}
else
{
//生產環境異常處理
app.UseExceptionHandler("/Shared/Error");
}
//使用靜態文件
app.UseStaticFiles();
//使用Mvc,設置默認路由為系統登錄
app.UseMvc(routes =>
{
routes.MapRoute(
name: "default",
template: "{controller=Login}/{action=Index}/{id?}");
});
SeedData.Initialize(app.ApplicationServices); //初始化數據
}
運行程序。查看數據庫,發現初始化數據已經生成成功。
3 踩過的一些坑
- 使用Guid類型的主鍵一定要添加"Npgsql.EntityFrameworkCore.PostgreSQL.Design": "1.0.1"的引用,注意1.0.0版本是不支持的。
- 要想使用Guid類型的主鍵一定要在DbContext的 OnModelCreating 重寫方法中啟用uuid的擴展 builder.HasPostgresExtension("uuid-ossp");
- 關於多對關系的實體設計
在以前的EntityFramework中,多對多關系的實體,只需要創建兩個實體,兩個實體分別包含一個對方集合的導航屬性即可,是不需要創建關聯實體類的。如,User實體中包含一個ICollection<Role> Roles的導航屬性,同時Role實體中包含一個ICollection<User> Users的導航屬性,EF會根據實體間的關系自動創建一個User_Role中間表,若想修改中間表名,進行相關配置即可。
EF Core中必須創建關聯關系的實體才行。
- EF Core暫不支持LayzingLoad
4 總結
本節主要是研究怎樣通過EntityFramework Core使用PostgreSQL,通過CodeFirst數據庫遷移的方式根據設計好的實體進行數據庫的創建,最后我們根據系統需要,進行了一些相關數據的初始化。
接下來要實現用戶登錄功能。









