PostgreSQL Array 陣列型別與 FreeSql 打出一套【組合拳】

2022-06-07 15:02:24

前言

PostgreSQL 是世界公認的功能最強大的開源資料庫,除了基礎資料型別 int4/int8/varchar/numeric/timestamp 等,還支援 int4[]/int8[]/varchar[]/numeric[]/timestamp[] 陣列型別、hstore 型別(類似 c# Dictionary<string, string>)、gis 型別。

選擇一項技術一定是可以幫助我們提升效率,並且使用一定是非常簡便的,才能讓我們賺取更多時間,早點下班甚至上班摸魚。這篇文章主要講陣列型別,如何與 FreeSql 打出簡便高效的【組合拳】。

PostgreSQL 可以為每一種型別建立陣列,比如 int4 對應的陣列型別是 int4[]、varchar 對應的資料型別是 varchar[]。

PostgreSQL 雖然支援多維陣列,但是不建議使用,因為實際使用中會帶來很多操作麻煩,違背了使用簡便的初衷。一維陣列足夠應付很多場景。

FreeSql 本身已經支援五種導航屬性,OneToOne/ManyToOne/OneToMany/ManyToMany/Parent,為它們量身打造了級聯儲存、貪婪載入、延遲載入、級聯刪除(遞迴)、CTE遞迴查詢等功能。

今天 FreeSql 為 PostgreSQL Array 陣列型別提供了第六種新的導航屬性 PgArrayToMany 專屬功能。


issues #1145

Feature 特性:對陣列做導航

簡要描述原因:pg 之類的資料庫支援陣列型別,但是沒有對陣列做導航支援

使用場景:避免無必要的中間表

class User
{
  public int[] RoleIds { get; set; }
  public Role[] Roles  { get; set; }
}
class Role
{
  public int Id { get; set; }
}

解決方案

經過多方需求討論之後,設定了【功能目標】如下:(已釋出版本 v3.2.666-preview20220606)

功能名稱:PostgreSQL 【陣列型別】的【導航屬性】專屬功能

public enum TableRefType
{
    OneToOne, ManyToOne, OneToMany, ManyToMany,
    PgArrayToMany //PgArray 專用導航型別
}

方式一:select * from Role where Id in (RoleIds)

class User
{
    public int[] RoleIds { get; set; }
    [Navigate(nameof(RoleIds))]
    public List<Role> Roles { get; set; }
}

方式二:select * from User where RoleIds @> ARRAY[Id]::int4[]

class Role
{
    public int Id { get; set; }
    [Navigate(nameof(User.RoleIds))]
    public List<User> Users { get; set; }
}

1、支援 LazyLoading 延時載入

2、支援 IncludeMany、IncludeByPropertyName 貪婪載入

fsql.Select<User>().IncludeMany(a => a.Roles).ToList();
fsql.Select<User>().IncludeByPropertyName("Roles").ToList();

fsql.Select<Role>().IncludeMany(a => a.Users).ToList();
fsql.Select<Role>().IncludeByPropertyName("Users").ToList();

3、支援 Lambda 子查詢

fsql.Select<User>().Where(a => a.Roles.Any(b => b.RoleName == "管理員")).ToList();
fsql.Select<User>().Where(a => a.Roles.Count() > 0).ToList();

fsql.Select<Role>().Where(a => a.Users.Any(b => b.UserName == "Admin")).ToList();
fsql.Select<Role>().Where(a => a.Users.Count() > 0).ToList();

//... 以及 AsSelect()

4、不支援級聯儲存、級聯刪除(因機制衝突)


資料補充

至此,FreeSql 支援了六種導航屬性。

FreeSql 五種導航屬性進化過程 OneToOne/ManyToOne/OneToMany/ManyToMany/Parent(文章內不包括 PgArrayToMany 介紹)

FreeSql 是 .Net ORM,能支援 .NetFramework4.0+、.NetCore、Xamarin、XAUI、Blazor、以及還有說不出來的執行平臺,因為程式碼綠色無依賴,支援新平臺非常簡單。目前單元測試數量:5000+,Nuget下載數量:180K+,原始碼幾乎每天都有提交。

QQ群:4336577(已滿)、8578575(線上)、52508226(線上)

FreeSql 主要優勢在於易用性上,基本是開箱即用,在不同資料庫之間切換相容性比較好。作者花了大量的時間精力在這個專案,肯請您花半小時瞭解下專案,謝謝。功能特性如下:

  • 支援 CodeFirst 對比結構變化遷移;
  • 支援 DbFirst 從資料庫匯入實體類;
  • 支援 豐富的表示式函數,自定義解析;
  • 支援 批次新增、批次更新、BulkCopy;
  • 支援 導航屬性,貪婪載入、延時載入、級聯儲存;
  • 支援 讀寫分離、分表分庫,租戶設計;
  • 支援 MySql/SqlServer/PostgreSQL/Oracle/Sqlite/達夢/神通/人大金倉/翰高/MsAccess;

FreeSql 使用非常簡單,只需要定義一個 IFreeSql 物件即可:

static IFreeSql fsql = new FreeSql.FreeSqlBuilder()
    .UseConnectionString(FreeSql.DataType.MySql, connectionString)
    .UseAutoSyncStructure(true) //自動同步實體結構到資料庫
    .Build(); //請務必定義成 Singleton 單例模式

注意:單例不等於執行緒不安全,除了事務,實際內部是有連線池管理 Ado.net IDbConnection 物件,請放心大膽使用,不用糾結執行緒安全問題。

微軟製造了優秀的語言 c#,利用語言特性可以做一些非常好用的功能,在 ORM 中使用導航屬性非常適合。

  • ManyToOne(N對1) 提供了簡單的多表 join 查詢;

  • OneToMany(1對N) 提供了簡單可控的級聯查詢、級聯儲存功能;

  • ManyToMany(多對多) 提供了簡單的多對多過濾查詢、級聯查詢、級聯儲存功能;

  • Parent(父子關係) 提供了常用的 CTE查詢、刪除、遞迴功能;

  • PgArrayToMany(陣列導航) 提供了 pgsql array 陣列型別級聯查詢;

希望正在使用的、善良的您能動一動小手指,把文章轉發一下,讓更多人知道 .NET 有這樣一個好用的 ORM 存在。謝謝了!!

FreeSql 開源協定 MIT https://github.com/dotnetcore/FreeSql,可以商用,檔案齊全。QQ群:4336577(已滿)、8578575(線上)、52508226(線上)

如果你有好的 ORM 實現想法,歡迎給作者留言討論,謝謝觀看!