FreeSql 新的八大骚功能,.NETCore 你必须晓得的 ORM

兔子压倒窝边草 2019-07-01

前言

FreeSql 目前版本号 0.5.5,预计明年元旦发布 1.0.0,切莫小看了版本号,目前单元测试方法1350+,并且每个方法内的涵盖面又比较广(不信的话见下图),每一次版本发布都作了较多的测试工作。

FreeSql 新的八大骚功能,.NETCore 你必须晓得的 ORM

最近的一段时间,关注我们的人时不时会看见扩展包发布,今天振奋人心的功能主要是核心部分实现(扩展包今天当配角)。就不多啰嗦了,咱们直接入主题。

功能一:MapType 类型映射

使用 codefirst 时序列化 json 或 jsonb 数据类型报错

使用 postgresql + ef 配置数据映射关系,使用 FreeSql 的映射扩展时,对于json类型的数据映射出错。

这是来自 github 上的某个 issue,原因是用户的实体定义了 string,数据库类型为 json。FreeSql 本身支持了丰富的类型,不限于 json,但是限定了类型的映射,比如 JToken/JObject/JArray 的实体类型才可以映射至 PostgreSQL 数据库的 json 类型。另外虽然有 DbType 特性可以设置,但使用范围有限,不可跨越类型(如使用 string 可使用 DbType="char(100)")。

还有一些类似要求,如:将 enum 映射到数据库 varchar 的请求。。。。

到现在,我们已经彻底突破了这个障碍,基本可以做到随意映射类型。作为新项目开发,我们提供本身的默认类型映射已经非常人性化,提这些需求的人主要还是历史原因,咱们做程序维护工作的人员还是占比很高,千怪万怪只能怪 FreeSql 来得太迟。。。。

目前为 MapType 功能增加了大约 400 个单元测试方法。贴一段 demo 配置方法:

class EnumTestMap {
    public Guid id { get; set; }

    [Column(MapType = typeof(string))]
    public ToStringMapEnum enum_to_string { get; set; }
    [Column(MapType = typeof(string))]
    public ToStringMapEnum? enumnullable_to_string { get; set; }

    [Column(MapType = typeof(int))]
    public ToStringMapEnum enum_to_int { get; set; }
    [Column(MapType = typeof(int?))]
    public ToStringMapEnum? enumnullable_to_int { get; set; }

    [Column(MapType = typeof(string))]
    public BigInteger biginteger_to_string { get; set; }
    [Column(MapType = typeof(string))]
    public BigInteger? bigintegernullable_to_string { get; set; }
}
public enum ToStringMapEnum { 中国人, abc, 香港 }

应该不需要解释了吧?

细看一下,实体内有 BigInteger 类型,这可是数据库无法表示的类型,现在就是可以使用(没辙)。但请注意:BigInteger 仅仅是 CURD 方便, Equals == 判断可以使用,无法使用 + - * / < > 等操作;

默认映射

csharpMySqlSqlServerPostgreSQLOracleSqlite
bool , bool?bit(1)bitboolnumber(1)boolean
sbyte , sbyte?tinyint(3)smallintint2number(4)smallint
short , short?smallint(6)smallintint2number(6)smallint
int , int?int(11)intint4number(11)integer
long , long?bigint(20)bigintint8number(21)integer
byte , byte?tinyint(3) unsignedtinyintint2number(3)int2
ushort , ushort?smallint(5) unsignedintint4number(5)unsigned
uint , uint?int(10) unsignedbigintint8number(10)decimal(10,0)
ulong , ulong?bigint(20) unsigneddecimal(20,0)numeric(20,0)number(20)decimal(21,0)
double , double?doublefloatfloat8float(126)double
float , float?floatrealfloat4float(63)float
decimal , decimal?decimal(10,2)decimal(10,2)numeric(10,2)number(10,2)decimal(10,2)
Guid , Guid?char(36)uniqueidentifieruuidchar(36 CHAR)character(36)
TimeSpan , TimeSpan?timetimetimeinterval day(2) to second(6)bigint
DateTime , DateTime?datetimedatetimetimestamptimestamp(6)datetime
DateTimeOffset , DateTimeOffset?--datetimeoffsettimestamp(6) with local time zone-
Enum , Enum?enumintint4number(16)mediumint
FlagsEnum , FlagsEnum?setbigintint8number(32)bigint
byte[]varbinary(255)varbinary(255)byteablobblob
stringvarchar(255)nvarchar(255)varchar(255)nvarchar2(255)nvarchar(255)
MygisPointpoint----
MygisLineStringlinestring----
MygisPolygonpolygon----
MygisMultiPointmultipoint----
MygisMultiLineStringmultilinestring----
MygisMultiPolygonmultipolygon----
BitArray--varbit(64)--
NpgsqlPoint , NpgsqlPoint?--point--
NpgsqlLine , NpgsqlLine?--line--
NpgsqlLSeg , NpgsqlLSeg?--lseg--
NpgsqlBox , NpgsqlBox?--box--
NpgsqlPath , NpgsqlPath?--path--
NpgsqlPolygon , NpgsqlPolygon?--polygon--
NpgsqlCircle , NpgsqlCircle?--circle--
(IPAddress Address, int Subnet) , (IPAddress Address, int Subnet)?--cidr--
IPAddress--inet--
PhysicalAddress--macaddr--
NpgsqlRange<int> , NpgsqlRange<int>?--int4range--
NpgsqlRange<long> , NpgsqlRange<long>?--int8range--
NpgsqlRange<decimal> , NpgsqlRange<decimal>?--numrange--
NpgsqlRange<DateTime> , NpgsqlRange<DateTime>?--tsrange--
PostgisPoint--geometry--
PostgisLineString--geometry--
PostgisPolygon--geometry--
PostgisMultiPoint--geometry--
PostgisMultiLineString--geometry--
PostgisMultiPolygon--geometry--
PostgisGeometry--geometry--
PostgisGeometryCollection--geometry--
Dictionary<string, string>--hstore--
JToken--jsonb--
JObject--jsonb--
JArray--jsonb--
数组--以上所有类型都支持--
以上类型和长度是默认值,可手工设置,如 string 属性可指定 [Column(DbType = "varchar(max)")]

功能二:唯一键(Unique)

class AddUniquesInfo {

    public Guid id { get; set; }
    [Column(Unique = "uk_phone")]
    public string phone { get; set; }

    [Column(Unique = "uk_group_index")]
    public string group { get; set; }
    [Column(Unique = "uk_group_index")]
    public int index { get; set; }

    [Column(Unique = "uk_group_index222")]
    public string index22 { get; set; }
}

Unique 指定相同的标识,代表联合唯一键,现已支持迁移。

功能三:弱类型(实体)

之前在操作实体时,必须传统泛型参数,现在可以实现弱类型实体的操作。以 Repository 为例:

var repos = fsql.GetGuidRepository<object>();
repos.AsType(typeof(AddUpdateInfo));

var item = new AddUpdateInfo();
repos.Insert(item);

item.Clicks += 1;
repos.InsertOrUpdate(item);

var item2 = repos.Find(item.Id) as AddUpdateInfo;
Assert.Equal(item.Clicks, item2.Clicks);

repos.DataFilter.Apply("xxx", a => (a as AddUpdateInfo).Clicks == 11);
Assert.Null(repos.Find(item.Id));

然后呢,DbContext 也支持同样的操作。

dotnet add package FreeSql.DbContext

功能四:ToList & Mapper

现在支持 ToList(a => new Dto()) 这样的简单数据映射。

什么意思?即 Dto 只要有属性名与实体属性相同,就会根据匹配到的字段查询(不是查询所有字段回来再映射)。

然后这个骚操作,还支持多表查询的映射,怎么解决多表存在相同名字的字段问题呢?优先级规则,它会依次序匹配 LeftJoin/InnerJoin/RightJoin 的实体。

功能五:ToList(true) 贪婪加载

以前 .ToList() 会加载两级Join对象;

现在 ISelect.ToList(includeNestedMembers: true) 贪婪加载所有 LeftJoin/InnerJoin/RightJoin 导航数据,不论对象的层级;

功能六:WhereDynamic 动态条件

支持传入动态对象如:主键值 | new[]{主键值1,主键值2} | TEntity1 | new[]{TEntity1,TEntity2} | new{id=1}。

也就是说 WhereDynaimc 方法输入类型为 object,是不是很方便?还支持联合主键呢。

功能七:IAdo.Query 多个结果集

var result = fsql.Ado.Query<T1, T2>("select from t1; select from t2");

功能八:开发环境之利器:MVC 中间件 FreeSql.AdminLTE

大约是前一段时间的某一天(废话),因为使用 FreeSql 的某项目需要做一个简单的后台功能,以便录入或管理数据。在实施的过程中好怀念当初 dotnetGen 生成器的味道,用它产生 curd 基本功能几乎是秒做;

FreeSql.AdminLTE,是的就是它,前段时间发布过一次。

它是 FreeSql 衍生出来的 .NETCore MVC 中间件、中间件、中间件(重复三遍)扩展包,基于 AdminLTE 前端框架动态产生实体的增删查改界面;

输入:实体1、实体2、实体3

输出:后台管理的功能

只需要传入实体,就可以形成 curd 的管理功能,是不是有些骚啊~~~

先发一张运行后的图片尝个鲜:

FreeSql 新的八大骚功能,.NETCore 你必须晓得的 ORM

这是根据实体产生 curd 界面的 mvc 中间件,开发时预览数据好方便啊。看完预览图不由得再感叹一次 FreeSql 的易用性,那句口号:做 .NETCore 最方便的 ORM! 没有说错。。。作者多次提及:“我们是日式简约风格,没那么复杂的用法”,也验证了这一点。。

添加/修改

中件间产生的界面包括添加、修改数据的功能,普通实体的根据属性的类型与 Html5 UI 一一映射;

比较特殊的映射规则:

c# 类型Html5
布尔复选框
枚举下拉选择
日期日期控件
ManyToOne 导航属性下拉选择
ManyToMany 导航属性多选器

等等。。。

什么情况会产生【上传文件】控件?
有兴趣的可以了解源码,目前没有开放在外部配置。

查询/过滤

中件间为每个实体提供了分页列表查询,每页为20条数据;

除此外,还提供了过滤条件的支持,规则是根据导航属性(ManyToOne、ManyToMany)。比如【文章实体】,内含有【分类id】+【分类对象】,则【文章】列表页会出现按【分类】筛选的UI,详见上面的 demo 示意图,或者下载对应的 demo 版本运行;

删除

中件间为每个实体提供了批量删除的功能;

测试 demo

我们习惯用 sqlite 做测试库,测试完毕直接删除目录,不留垃圾数据,所以下面的 demo 不需要修改任何地方,运行时自动建库、建表;

提供 .net core 2.1、2.2 两种环境的测试 demo 下载:

Demo for dotnet 2.1.zipDemo for dotnet 2.2.zip

FreeSql 新的八大骚功能,.NETCore 你必须晓得的 ORM

第一步:

dotnet restore

第二步:

dotnet run

思考

一番惊喜过后,你应该会考虑实用性,这样做有什么价值,可用于什么样的场景?

这个扩展包简单的输入,产生巨量的功能反馈。目前来说它是死板的,对外提供的扩展性几乎为零,这样也就限定了它的应用场景。

不合适的场景

1、它不可替代我们自身开发的后台管理系统;

2、它不适合摆放在公网正式环境,存在数据安全问题;

3、欢迎补充。。。;

谈谈定位

目前的定位是这样的,在开发环境中使用,查阅预览实体数据,同时也比较方便的管理测试数据。

一段拥有无比力量的小段代码,也是中间件界面的功能开启:

//可以配置子目录访问,如:/testadmin/
app.UseFreeAdminLTE("/",
    typeof(Entities.Song),
    typeof(Entities.Tag));

观后抽奖

我们一直在发布纯技术干货的分享文章,FreeSql 已经基本完成 .NETCore 最方便的 ORM 使命,我们正在筹备生态的建立,比如 ABP 中如何使用 FreeSql 的实现,需要各种各样的扩展包,好多好多工作量。有没有大神愿意无偿参与做这件事情,好吧。。应该没有人!!如果你回心转意了,欢迎联系我们。

欢迎持续关注我们,做 .NETCore 最方便的 ORM !

(QQ群:4336577)

github: https://github.com/2881099/FreeSql

说好的抽奖呢???

相关推荐