首页 » Web前端 » phpmysqlifree技巧_C 数据操作系列 19 FreeSql 入坑介绍长篇警告

phpmysqlifree技巧_C 数据操作系列 19 FreeSql 入坑介绍长篇警告

访客 2024-12-02 0

扫一扫用手机浏览

文章目录 [+]

大略先容一下,FreeSql 是NCC组织的沙盒级项目,是一款功能强大的 ORM 组件,支持 .NET Core、.NET Framework 和 Xamarin。
目前 FreeSql 支持以下数据库:MySQL、PostgreSQL、SqlServer、Oracle、Sqlite、Odbc、微软 Access 以及国产数据库达梦。

也便是说也是一个由海内精良开拓者掩护的精良项目,初步看了下功能很完好。
小伙伴们有韶光可以去瞅瞅。
下图是我从它GitHub仓库里复制过来的。
可以瞥见支持的功能还是相称多的。

phpmysqlifree技巧_C 数据操作系列  19 FreeSql 入坑介绍长篇警告

关于NCC社区,是.net core的一个开源社区,也是海内最大的.net core开源社区

phpmysqlifree技巧_C 数据操作系列  19 FreeSql 入坑介绍长篇警告
(图片来自网络侵删)
1. 初步利用

照例,没安装就没有调用。
以是,在创建项目之后,安装一下吧:

dotnet add package FreeSql

然后创建一个IFreeSql工具:

public class FreeSqlContext{ public static IFreeSql FreeSqlConnect { get; } = new FreeSql.FreeSqlBuilder() .UseConnectionString(FreeSql.DataType.Sqlite, @"Data Source=document.db") .UseAutoSyncStructure(true) //自动同步实体构造到数据库 .Build();}

由于官方哀求将IFreeSql工具声明为单例模式,以是我在这里利用了静态属性。

这种写法是C#的一种语法糖,只有get表示该属性是一个只能读的属性(与只读属性有个奇妙的差距),等号后面表示该属性第一次赋值的内容。

创建一个普通的Model类:

public class Model{ public int Id { get; set; } public int StringLength { get; set; } public string Name { get; set; }}1.1 大略插入

然后试一下插入数据:

var row = FreeSqlContext.FreeSqlConnect.Insert(new Model{ Name = "测试", StringLength = 10}).ExecuteAffrows();

提示如图内容,须要我们手动安装一下FreeSql的SQLite驱动,安装之后:

dotnet add packages FreeSql.Provider.Sqlite

FreeSql针对各种受支持的数据库都单独开拓了驱动包,统一命名为:

FreeSql.Provider.<数据库类型>

安装完成后,重新运行后顺利完成实行,顺便帮你把数据库也天生好了(这一点我觉得挺好的),同时天生了一个主键为Id的Model表:

create table Model( Id INTEGER primary key, StringLength INTEGER not null, Name NVARCHAR(255));1.2 大略查询

接下来大略的查询一下刚刚插入的数据:

var list = FreeSqlContext.FreeSqlConnect.Queryable<Model>().ToList();

可以创造,查询利用还是非常方便的。

1.3 大略更新

FreeSql的更新与其他框架比较略显繁芜,这里先展示一种更新办法:

list[0].Name = "修正测试";row = FreeSqlContext.FreeSqlConnect.Update<Model>().SetSource(list[0]).ExecuteAffrows();

先声明要更新的类型是Model,然后设置更新源。

1.4 大略删除

row = FreeSqlContext.FreeSqlConnect.Delete<Model>(new[] { list[0] }).ExecuteAffrows();

删除之前获取的数据。

大略的看,FreeSql设计的增编削查都因此命令的形式进行的,在实际调用ExcuteXXX之前数据并不会保存到数据库中。

图文无关

2. 增编削查详解

在上一节中我们大略的利用了一下增编削查, 这一节将为大家详细剖析一下FreeSql的增编削查。

2.1 新增

IInsert<T1> Insert<T1>() where T1 : class;IInsert<T1> Insert<T1>(T1 source) where T1 : class;IInsert<T1> Insert<T1>(IEnumerable<T1> source) where T1 : class;IInsert<T1> Insert<T1>(List<T1> source) where T1 : class;IInsert<T1> Insert<T1>(T1[] source) where T1 : class;

这是IFreeSql接口里声明的Insert方法,通过方法我们可以看到插入单数据插入以及多数据插入,并且返回一个IInsert<T1>的接口。
当然也可以不传入数据直接获取一个IInsert接口实例。
这几个方法很大略,我们就不在这多费韶光了,然后跳进IInsert里,看一看里面有哪些方法吧。

先来这样一组方法:

IInsert<T1> AppendData(T1 source);IInsert<T1> AppendData(T1[] source);IInsert<T1> AppendData(IEnumerable<T1> source);

这些方法可往后续为IInsert连续添加数据,以便实行更多的插入。

IInsert<T1> IgnoreColumns(string[] columns);IInsert<T1> IgnoreColumns(Expression<Func<T1, object>> columns);

设置在插入过程中忽略的列,设置之后这些列将不会插入到数据库中。
个中 Expression<Func<T1, object>>表示一个包含列名属性的匿名工具。

IInsert<T1> InsertColumns(string[] columns);IInsert<T1> InsertColumns(Expression<Func<T1, object>> columns);

设置只插入这些列,其他的列将不会被插入。

通过调用以下方法将实行插入:

int ExecuteAffrows();// 返回受影响的列

long ExecuteIdentity();// 返回自增主键值

这个方法须要实体类的主键标记为自增(这部分内容见下一节)。
如果启用了批量插入模式,该值将返回末了一个数据的主键值。

List<T1> ExecuteInserted();// 返回插入后的数据

这个方法官方标注只在Postgresql/SqlServer有效果。

这是插入基本内容,相对而言插入比较大略。

2.2 删除

这次换个顺序,由于删除的方法在这里相对大略一些。
FreeSql对付单表的数据删除相对克制而谨慎。
那么就让我们大略看一下如何进行删除吧。

IDelete<T1> Delete<T1>() where T1 : class;

设置泛型类型,创建一个删除器(我给起的名,官方没给起名,也便是一个IDelete接口实例)。

IDelete<T1> Delete<T1>(object dywhere) where T1 : class;

这个方法很故意思,支持的相称广泛。

以下是官方给的注释:

主键值 | new[]{主键值1,主键值2} | TEntity1 | new[]{TEntity1,TEntity2} |new{id=1}

根据实际表现来看,会删除对应主键的数据。
如果传入的是实体的话,会自动剖析对应实体的主键,然后把这个数据标记为待删除。

记住这种办法,由于在后续的Update中会用到。

IFreeSql中的删除都不会立即删除,都会返回一个IDelete实例,与IInsert一样须要手动调用ExcuteXXX方法。

那么我们来看一下IDelete里的方法:

IDelete<T1> Where(Expression<Func<T1, bool>> exp);IDelete<T1> Where(string sql, object parms = null);IDelete<T1> Where(T1 item);IDelete<T1> Where(IEnumerable<T1> items);

大略看一下方法,可以通过方法和参数就能知道个中含义。

须要把稳的是,如果利用exp 做批量删除的话,只能用实体类的属性作为条件,不能利用导航属性。

利用sql语句的话,可以利用参数化写法如下:Where("id = ?id", new { id = 1 }),如果有多个条件的话sql里用and拼接。

IDelete<T1> WhereDynamic(object dywhere, bool not = false);

这里的dywhere与Delete的dywhere一样,not 如果设置为true,则表示删除除此之外的工具。

FreeSql在设计删除模式时,如果在IFreeSql.Delete中传入参数,后续连续调用Where或者WhereDynamic的话,两次因此and 的形式拼接的条件:

list = FreeSqlContext.FreeSqlConnect.Queryable<Model>().ToList();FreeSqlContext.FreeSqlConnect.Delete<Model>(list[0]).WhereDynamic(list[2]).ExecuteAffrows();FreeSqlContext.FreeSqlConnect.Delete<Model>(list[0]).Where(t=>t.Id > 10).ExecuteAffrows();

分别天生了如下SQL语句:

DELETE FROM "Model" WHERE ("Id" = 1) AND ("Id" = 11)----------------------------DELETE FROM "Model" WHERE ("Id" = 1) AND ("Id" > 10)

额,以是调用删除的时候最好把稳一下,由于条件冲突的话,可能数据不会发生任何变革。

实行删除:

int ExecuteAffrows();//返回被影响的行数List<T1> ExecuteDeleted();// 返回被删除的数据,一样只有 Postgresql/SqlServer 有效果2.3 更新

IUpdate<T1> Update<T1>() where T1 : class;IUpdate<T1> Update<T1>(object dywhere) where T1 : class;

同样,开启一个更新器(获取一个IUpdate示例),这里dywhere与删除支持的内容是一样的。
不过,有一点不同的是:

row = FreeSqlContext.FreeSqlConnect.Update<Model>(list[0]).ExecuteAffrows();

不会有任何数据发生变动。
嗯,这点与Delete完备不一样。
大略理解一下,在这里FreeSql只是解析了数据里的实体,但并没有从传入的实体解析出更新SQL语句。

接下来,进入IUpdate:

IUpdate<T1> UpdateColumns(string[] columns);IUpdate<T1> UpdateColumns(Expression<Func<T1, object>> columns);IUpdate<T1> IgnoreColumns(Expression<Func<T1, object>> columns);IUpdate<T1> IgnoreColumns(string[] columns);

设置要更新的列和要忽略的列,两者相互冲突。

示例:

row = FreeSqlContext.FreeSqlConnect.Update<Model>(list[0]).UpdateColumns(new[] { "Name" }).ExecuteAffrows();

是不是以为欢天喜地的以为会更新了,答案很残酷,没有。
依旧返回0。
说到这里了,FreeSql在更新上,须要额外指定更新的数据来源:

IUpdate<T1> SetSource(T1 source);IUpdate<T1> SetSource(IEnumerable<T1> source);

也便是,FreeSql会从source解析出须要更新的字段,然后利用Update/Ignore来设置只更新或忽略哪些列。

终极示例:

row = FreeSqlContext.FreeSqlConnect.Update<Model>(list[0]) .SetSource(list[0]).UpdateColumns(new[] { "Name" }).ExecuteAffrows();row = FreeSqlContext.FreeSqlConnect.Update<Model>(list[0]) .SetSource(list).UpdateColumns(new[] { "Name" }).ExecuteAffrows();row = FreeSqlContext.FreeSqlConnect.Update<Model>(new[] { list[0] ,list[1]}) .SetSource(list[0]).UpdateColumns(new[] { "Name" }).ExecuteAffrows();row = FreeSqlContext.FreeSqlConnect.Update<Model>(new[] { list[0], list[1] }) .SetSource(list).UpdateColumns(new[] { "Name" }).ExecuteAffrows();

然后天生如下SQL:

UPDATE "Model" SET "Name" = @p_0 WHERE ("Id" = 1) AND ("Id" = 1)--------------------------UPDATE "Model" SET "Name" = CASE "Id"WHEN 1 THEN @p_0WHEN 10 THEN @p_1WHEN 11 THEN @p_2WHEN 12 THEN @p_3WHEN 13 THEN @p_4WHEN 14 THEN @p_5WHEN 15 THEN @p_6WHEN 16 THEN @p_7WHEN 17 THEN @p_8WHEN 18 THEN @p_9WHEN 19 THEN @p_10WHEN 20 THEN @p_11WHEN 21 THEN @p_12WHEN 22 THEN @p_13WHEN 23 THEN @p_14WHEN 24 THEN @p_15 ENDWHERE ("Id" IN (1,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24)) AND ("Id" = 1)--------------------UPDATE "Model" SET "Name" = @p_0 WHERE ("Id" = 1) AND ("Id" = 1 OR "Id" = 10)--------------------UPDATE "Model" SET "Name" = CASE "Id"WHEN 1 THEN @p_0WHEN 10 THEN @p_1WHEN 11 THEN @p_2WHEN 12 THEN @p_3WHEN 13 THEN @p_4WHEN 14 THEN @p_5WHEN 15 THEN @p_6WHEN 16 THEN @p_7WHEN 17 THEN @p_8WHEN 18 THEN @p_9WHEN 19 THEN @p_10WHEN 20 THEN @p_11WHEN 21 THEN @p_12WHEN 22 THEN @p_13WHEN 23 THEN @p_14WHEN 24 THEN @p_15 ENDWHERE ("Id" IN (1,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24)) AND ("Id" = 1 OR "Id" = 10)

可以看出,如果在天生IUpdate实例的时候,传入数据再利用SetSource进行更新会比较诡异。
以是SetSource的正常利用办法是,获取IUpdate实例的时候,不传dywhere,直接获取一个空IUpdate。

那么dywhere该在什么时候利用呢?

row = FreeSqlContext.FreeSqlConnect.Update<Model>(list[0]).Set(t => t.StringLength + 1).ExecuteAffrows();

通过调用Set/SetDto/SetIf三种方法进行更新,当然了这三种方法并不局限于利用了dywhere参数。

IUpdate<T1> Set<TMember>(Expression<Func<T1, TMember>> exp);IUpdate<T1> Set<TMember>(Expression<Func<T1, TMember>> column, TMember value);IUpdate<T1> SetDto(object dto);IUpdate<T1> SetIf<TMember>(bool condition, Expression<Func<T1, TMember>> exp);IUpdate<T1> SetIf<TMember>(bool condition, Expression<Func<T1, TMember>> column, TMember value);

个中:

Expression<Func<T1, TMember>> exp 表示在字段本身值的根本上进行操作Expression<Func<T1, TMember>> column, TMember value 表示将 column设置 valueobject dto 一个包含要更新属性和值的匿名类,或者一个字典类型(键为要更新的列,值为对应列的值)bool condition 表示知足条件则更新,否则将不进行更新

IUpdate也供应了Where模式:

IUpdate<T1> Where(Expression<Func<T1, bool>> exp);IUpdate<T1> Where(string sql, object parms = null);IUpdate<T1> Where(T1 item);IUpdate<T1> Where(IEnumerable<T1> items);IUpdate<T1> WhereDynamic(object dywhere, bool not = false);

终极更新该当如下:

FreeSqlContext.FreeSqlConnect.Update<Model>(list[0]).Set(t => t.StringLength + 1).ExecuteAffrows();FreeSqlContext.FreeSqlConnect.Update<Model>(list[0]).SetDto(new { Name="测试2" }).ExecuteAffrows();FreeSqlContext.FreeSqlConnect.Update<Model>(list[0]).SetIf(true, t => t.Name + 1).ExecuteAffrows();// 或者以下模式FreeSqlContext.FreeSqlConnect.Update<Model>() .Where(t => true) .Set(t => t.StringLength + 1) .ExecuteAffrows();// 或者FreeSqlContext.FreeSqlConnect.Update<Model>(1) .Set(t => t.StringLength + 1) .ExecuteAffrows();

实行更新:

int ExecuteAffrows();// 返回受影响的行数List<T1> ExecuteUpdated();// 嗯, 只有 Postgresql/SqlServer 有效果2.4 查询

FreeSql的查询有两种办法,一种是利用FreeSql的ISelect方法,一种是利用扩展出来的Queryable方法,两者终极返回是一样的,均返回了一个ISelect实例。

那先来悄悄看一下两个方法的声明吧:

ISelect<T1> Select<T1>() where T1 : class;ISelect<T1> Select<T1>(object dywhere) where T1 : class;// 扩展方法在 FreeSqlGlobalExtensions 类public static ISelect<T> Queryable<T>(this IFreeSql freesql) where T : class;

个中有一个闪闪放光的 dywhere,与Update/Delete一样,也是通过传入的属性解析到主键值获取对应的数据。

那么进入ISelect一探究竟吧:

暂且忽略多个泛型支持的方法:

T1 First()TDto First<TDto>();TReturn First<TReturn>(Expression<Func<T1, TReturn>> select);T1 ToOne();TDto ToOne<TDto>();TReturn ToOne<TReturn>(Expression<Func<T1, TReturn>> select);First和ToOne都是返回第一条数据TDto 表示要查询出来的字段合集,列名与数据表中逐一对应Expression<Func<T1, TReturn>> select 类型投影,通过lambda语句建立T1到TReturn之间的关系

返回多个:

List<T1> ToList(bool includeNestedMembers = false);List<TDto> ToList<TDto>();List<TReturn> ToList<TReturn>(Expression<Func<T1, TReturn>> select);includeNestedMembers : false: 返回 2级 LeftJoin/InnerJoin/RightJoin 工具;true: 返回所有 LeftJoin/InnerJoin/RightJoin的导航数据

其他方法:

long Count();// 返回数目ISelect<T1> Distinct();//去重ISelect<T1> Skip(int offset);// 忽略几个ISelect<T1> Take(int limit);// 获取前几个ISelect<T1> OrderBy<TMember>(Expression<Func<T1, TMember>> column);// 排序ISelect<T1> OrderBy<TMember>(bool condition, Expression<Func<T1, TMember>> column);// 排序ISelect<T1> OrderByDescending<TMember>(Expression<Func<T1, TMember>> column); // 降序ISelect<T1> OrderByDescending<TMember>(bool condition, Expression<Func<T1, TMember>> column);// 降序decimal Sum<TMember>(Expression<Func<T1, TMember>> column);// 求和double Avg<TMember>(Expression<Func<T1, TMember>> column);// 求均匀数

设置查询条件:

ISelect<T1> Where(Expression<Func<T1, bool>> exp);ISelect<T1> WhereIf(bool condition, Expression<Func<T1, bool>> exp);ISelect<T1> Where(string sql, object parms = null);

把稳与dywhere之间是并列关系。

关于查询FreeSql做了很多优化,更多内容可以查阅官方文档。
到目前为止,这些方法已经可以知足一个项目的利用了。

图文无关

3. 总结

FreeSql可以说结合了很多精良的ORM框架内容,而且针对不同的办法分成了不同的插件形式,使主干可以轻装上阵。

这是官方文档中关于不同利用习气的先容。

关于FreeSql的根本内容就到这里了,如果对FreeSql有更多的需求的话,可以踊跃吐槽哦~~如果有小伙伴还想看的话,我将会连续为大家讲解的。
关于FreeSql的更多内容欢迎点击扩展链接。

至此,2020-5-28 《C# 数据操作系列》暂时 完结(如果后续有其他好的ORM的话,还会连续更新的)。

求关注,求点赞,求转发~~有啥可以评论哟

标签:

相关文章

IT店铺上班,介绍数字时代的职场新潮流

随着互联网技术的飞速发展,我国已经迈入了一个全新的数字时代。在这个时代背景下,传统的办公模式逐渐被颠覆,新型办公方式层出不穷。其中...

Web前端 2024-12-27 阅读0 评论0

IT工作思路,探索科技与创新的融合之路

在当今这个信息化、数字化时代,IT行业已成为推动社会进步的重要力量。IT工作思路作为一种全新的思维方式,不仅引领着科技的发展,更在...

Web前端 2024-12-27 阅读0 评论0

抓易语言连接,开启编程新纪元的技术探索

在科技飞速发展的今天,编程已经成为现代社会不可或缺的一部分。而作为编程领域的重要分支,语言连接技术更是备受关注。其中,抓易语言连接...

Web前端 2024-12-27 阅读0 评论0