乐趣区

关于.net:PostgreSQL-Array-数组类型与-FreeSql-打出一套组合拳

前言

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 专属性能。


数组映射

FreeSql 反对 int[] 映射 int4[]

string[] 映射 varchar[]

DateTime[] 映射 timestamp[]

class Model
{public Guid Id { get; set;}
    public int[] TypeIds { get; set;}
    public Guid[] UserIds { get; set;}
}

等等,罕用的类型都能够间接用数组进行映射,之后就能够像一般类型一样进行 CRUD 操作了。

var model = new Model
{Id = Guid.NewGuid(),
    TypeIds = new int[] { 1,2,3},
    UserIds = new Guid[] { Guid.NewGuid(), Guid.NewGuid()}
};
fsql.Insert(model).ExecuteAffrows(); // 插入
fsql.Update<Model>().SetSource(model).ExecuteAffrows(); // 更新
fsql.Delete(model).ExecuteAffrows(); // 删除
List<Model> list = fsql.Select<Model>().ToList(); // 查问 

表达式解析:

fsql.Select<Model>().Where(a => a.TypeIds.Any()).ToSql();
fsql.Select<Model>().Where(a => a.TypeIds.Contains(3)).ToSql();
fsql.Select<Model>().ToSql(a => new
{NewTypeIds = a.TypeIds.Concat(new int [] {10, 11, 12})
});
fsql.Select<Model>().Where(a => a.TypeIds.Length > 0).ToSql();

如果不够用还能够自定义解析:

[ExpressionCall]
public static class DbFunc {
  // 必要定义 static + ThreadLocal
  static ThreadLocal<ExpressionCallContext> context = new ThreadLocal<ExpressionCallContext>();

  public static DateTime FormatDateTime(this DateTime that, string arg1)
  {
    var up = context.Value;
    if (up.DataType == FreeSql.DataType.PostgreSQL) // 重写内容
      up.Result = $"array_xxx({up.ParsedContent["that"]}, {up.ParsedContent["arg1"]})";
    return that;
  }
}

var sql1 = fsql.Select<Model>()
  .ToSql(a => a.CreateTime.FormatDateTime("xxx"));
//SELECT array_xxx(a."CreateTime", 'xxx') as1 
//FROM "Model" a

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 实现想法,欢送给作者留言探讨,谢谢观看!

退出移动版