FreeSql使用WithSql+ ToSQL 查询数据
FreeSql是一个支持.NET Core 2.1+、.NET Framework 4.0+ 以及 Xamarin的ORM(Object Relational Mapping)对象关系映射的组件
支持丰富的表达式函数及类型映射,但还是有不少开发者需要执行自定义SQL。
我一般会推荐他们使用
List<T> list = fsql.Ado.Query<T>("select * from t1");
等类似的操作,IAdo下有大量的ADO.NET基础的调用操作。但开发者还想使用类似Page,Skip,OrderBy等方法。鉴于fsql可以生成SQL,可以将不同的SQL组合,实现更加复杂的功能。
- 引用包
dotnet add packages FreeSql
dotnet add packages FreeSql.Provider.Sqlite
- .NET Core 单例 Startup.cs
public void ConfigureServices(IServiceCollection services)
{
IFreeSql fsql = new FreeSql.FreeSqlBuilder()
.UseConnectionString(FreeSql.DataType.Sqlite, @"Data Source=db1.db")
.UseAutoSyncStructure(true) //自动同步实体结构到数据库,FreeSql不会扫描程序集,只有CRUD时才会生成表。
.Build();
services.AddSingleton<IFreeSql>(fsql);
}
可使用以下方式实现
WithSql 自定义SQL
定义实体类
public class TestClass
{
[Column(Name = "ID", IsPrimary = true)]
public string No { get; set; }
public int? Age { get; set; }
public string Name { get; set; }
[Column(Name = "BIRTH_DAY")]
public DateTime? Birthday { get; set; }
public decimal Point { get; set; }
public Sex? Sex { get; set; }
}
public class TestClssDto
{
public string ID { get; set; }
public int? Age { get; set; }
}
不同的查询方式。
- 返回
DataTable - 返回
List<Tuplue>即List<(string,string)>元组 - 返回
List<object>且能支持分页 - 返回
List<TestClassDto>且能支持分页
1.返回DataTable
DataTable dt1 = _fsql.Select<object>()
.WithSql("select * from TestClass ")
.ToDataTable("ID,Age");
SELECT ID,Age
FROM(select * from TestClass ) a
2.返回DataTable
DataTable dt2 = _fsql.Select<object>()
.WithSql("select * from TestClass ")
.ToDataTable("*");
SELECT *
FROM ( select * from TestClass ) a
3.返回List<Tuplue> 即List<(string,string)> 元组
List<(string,string)> list1 = _fsql.Select<object>()
.WithSql("select * from TestClass ")
.ToList<(string, string)>("ID,Age");
SELECT ID, Age
FROM(select * from TestClass ) a
4.返回List<object>
var list2 = _fsql.Select<object>()
.WithSql("select * from TestClass ")
.ToList<object>("*");
SELECT *
FROM(select * from TestClass ) a
5.返回List<object> 且能支持分页
var list3 = _fsql.Select<object>().WithSql("select * from TestClass ")
.WhereIf(true, "1=1")
.Page(1, 10).OrderBy("ID DESC").ToList<object>("ID,Age");
SELECT ID, Age
FROM(select * from TestClass ) a
WHERE(1 = 1)
ORDER BY ID DESC
limit 0,10
6.返回List<TestClassDto>且能支持分页
var list4 = _fsql.Select<object>().WithSql("select * from TestClass ")
.WhereIf(true, "1=1")
.Page(1, 10)
.OrderBy("ID DESC")
.ToList<TestClssDto>("ID,Age");
SELECT ID, Age
FROM(select * from TestClass ) a
WHERE(1 = 1)
ORDER BY ID DESC
limit 0,10
通过 WithSql+ ToSQL实现 Union ALL 查询方法
1、二次 ISelect 查询:WithSql 使用多次,等于 UNION ALL 查询
WithSql 使用多次为 UNION ALL 查询,所以我们可以利用 ISelect.ToSql(FieldAliasOptions.AsProperty) 得到生成的 SQL,如下:
var sql1 = fsql.Select<Topic>()
.Where(a => a.Title.Contains("xxx"))
.ToSql();
var sql2 = fsql.Select<Topic>()
.Where(a => a.Title.Contains("yyy"))
.ToSql();
fsql.Select<Topic>()
.WithSql(sql1)
.WithSql(sql2)
.ToList();
SELECT * from (SELECT a.`Id`, a.`Clicks`, a.`TypeGuid`, a.`Title`, a.`CreateTime`
FROM ( SELECT a.`Id`, a.`Clicks`, a.`TypeGuid`, a.`Title`, a.`CreateTime`
FROM `tb_topic` a
WHERE ((a.`Title`) LIKE '%xxx%') ) a) ftb
UNION ALL
SELECT * from (SELECT a.`Id`, a.`Clicks`, a.`TypeGuid`, a.`Title`, a.`CreateTime`
FROM ( SELECT a.`Id`, a.`Clicks`, a.`TypeGuid`, a.`Title`, a.`CreateTime`
FROM `tb_topic` a
WHERE ((a.`Title`) LIKE '%yyy%') ) a) ftb
2、跨分表查询:AsTable 相同实体多次操作,等于 Union ALL 查询
var sql = fsql.Select<User>()
.AsTable((type, oldname) => "table_1")a
.AsTable((type, oldname) => "table_2")
.ToSql(a => a.Id);
select * from (SELECT a."Id" as1 FROM "table_1" a) ftb
UNION ALL
select * from (SELECT a."Id" as1 FROM "table_2" a) ftb
3、利用 ToSql 拼接新的 SQL,使用 IAdo 执行
var sql1 = fsql.Select<Topic>()
.Where(a => a.Id > 100 && a.Id < 200)
.ToSql(a => new { a.Id, a.Title }, FieldAliasOptions.AsProperty);
var sql2 = fsql.Select<Topic>()
.Where(a => a.Id > 1001 && a.Id < 1200)
.ToSql(a => new { a.Id, a.Title }, FieldAliasOptions.AsProperty);
fsql.Ado.CommandFluent($"{sql1} UNION ALL {sql2}")
.ExecuteDataTable();
分页问题
Union All 之后 如果直接 分页会有一个问题。请看具体示例
多次WithSql+Page存在问题:每个WithSql内都有一个Page分页
var sql1 = fsql.Select<Topic>()
.Where(a => a.Title.Contains("xxx"))
.ToSql();
var sql2 = fsql.Select<Topic>()
.Where(a => a.Title.Contains("yyy"))
.ToSql();
fsql.Select<Topic>().WithSql(sql1).WithSql(sql2).Page(1, 20).ToList();
SELECT * from (SELECT a.`Id`, a.`Clicks`, a.`TypeGuid`, a.`Title`, a.`CreateTime`
FROM ( SELECT a.`Id`, a.`Clicks`, a.`TypeGuid`, a.`Title`, a.`CreateTime`
FROM `tb_topic` a
WHERE ((a.`Title`) LIKE '%xxx%') ) a
limit 0,20) ftb
UNION ALL
SELECT * from (SELECT a.`Id`, a.`Clicks`, a.`TypeGuid`, a.`Title`, a.`CreateTime`
FROM ( SELECT a.`Id`, a.`Clicks`, a.`TypeGuid`, a.`Title`, a.`CreateTime`
FROM `tb_topic` a
WHERE ((a.`Title`) LIKE '%yyy%') ) a
limit 0,20) ftb
多个sql union all使用withsql,直接Page分页,会导致每个子表都生效,子表都生成分页。
WithSql 可以和 AsTable 实现分表的功能。
分表跨表查询的时候,分页是要向每个子表(即每个WithSql中的SQL分页)都生效。
解决方案
多次withsql,如需分页,需要按下面的二步操作
- 第一步:通过witsql,将二个sql组成一个sql。
var sql = fsql.Select<Topic>()
.WithSql("SELECT * FROM tb_topic where id > 11")
.WithSql("SELECT * FROM tb_topic where id < 10")
.ToSql("*")
如上生成的UOION ALL的sql
SELECT * from (SELECT *
FROM ( SELECT * FROM tb_topic where id > 11 ) a) ftb
UNION ALL
SELECT * from (SELECT *
FROM ( SELECT * FROM tb_topic where id < 10 ) a) ftb
- 第二步:之后 调用Page则是通过Union ALL后的结果上分页
var sql2 = g.mysql.Select<Topic>()
.WithSql(sql)
.Page(2, 10)
.ToSql();
SELECT a.`Id`, a.`Clicks`, a.`TypeGuid`, a.`Title`, a.`CreateTime`
FROM ( SELECT * from (SELECT *
FROM ( SELECT * FROM tb_topic where id > 11 ) a) ftb
UNION ALL
SELECT * from (SELECT *
FROM ( SELECT * FROM tb_topic where id < 10 ) a) ftb ) a
limit 10,10
更多
FreeSql使用WithSql+ ToSQL 查询数据的更多相关文章
- FreeSql (十五)查询数据
FreeSql在查询数据下足了功能,链式查询语法.多表查询.表达式函数支持得非常到位. IFreeSql fsql = new FreeSql.FreeSqlBuilder() .UseConnect ...
- FreeSql (五)插入数据
var connstr = "Data Source=127.0.0.1;Port=3306;User ID=root;Password=root;" + "Initia ...
- FreeSql (七)插入数据时忽略列
var connstr = "Data Source=127.0.0.1;Port=3306;User ID=root;Password=root;" + "Initia ...
- FreeSql (八)插入数据时指定列
插入数据时指定列,和忽略列对应,未被指定的列将被忽略. var connstr = "Data Source=127.0.0.1;Port=3306;User ID=root;Passwor ...
- FreeSql (九)删除数据
删除是一个非常危险的操作,FreeSql对删除支持并不强大,仅支持了单表有条件的删除方法. 不想过多的介绍拉长删除数据的系列文章,删除数据的介绍仅此一篇. 若Where条件为空的时候执行方法,Free ...
- FreeSql (十)更新数据
FreeSql支持丰富的更新数据方法,支持单条或批量更新,在特定的数据库执行还可以返回更新后的记录值. var connstr = "Data Source=127.0.0.1;Port=3 ...
- FreeSql (十一)更新数据 Where
var connstr = "Data Source=127.0.0.1;Port=3306;User ID=root;Password=root;" + "Initia ...
- FreeSql (十三)更新数据时忽略列
var connstr = "Data Source=127.0.0.1;Port=3306;User ID=root;Password=root;" + "Initia ...
- FreeSql 使用 ToTreeList/AsTreeCte 查询无限级分类表
关于无限级分类 第一种方案: 使用递归算法,也是使用频率最多的,大部分开源程序也是这么处理,不过一般都只用到四级分类. 这种算法的数据库结构设计最为简单.category表中一个字段id,一个字段fi ...
随机推荐
- 1.简单认识PHP和环境搭建
1.关于PHP PHP(Hypertext Perprocessor,超文本预处理器),是一种服务器端.跨平台.HTML嵌入式的脚本语言,其独特的语法混合了C.Java.和Perl语言的特点,是一种被 ...
- 利用DNS进行命令控制和搭建隧道
目录 利用DNS进行命令控制(DNS-Shell) 利用DNS搭建隧道 利用DNS进行命令控制(DNS-Shell) DNS-Shell是一款通过DNS信道实现交互式Shell的强大工具,该工具的服务 ...
- C#-窗体鼠标穿透
#region 窗体鼠标穿透 private const uint WS_EX_LAYERED = 0x80000; private const int WS_EX_TRANSPARENT = 0x2 ...
- 推荐算法-聚类-K-MEANS
对于大型的推荐系统,直接上协同过滤或者矩阵分解的话可能存在计算复杂度过高的问题,这个时候可以考虑用聚类做处理,其实聚类本身在机器学习中也常用,属于是非监督学习的应用,我们有的只是一组组数据,最终我们要 ...
- Linux-鸟菜-5-文件权限
Linux-鸟菜-5-文件权限 Linux作为多用户多任务的操作系统,文件权限以及目录配置相对于Windows的话应该更重要更细致一些.Linux一般将文件可存取的身份分为三个类别,分别是owner/ ...
- unresolved external symbol _WinMain@16
vc下,新建一个win32项目,就写了个main函数,打印hello ,出现了如标题所述的错误 原因: 你建立了一个WINDOWS应用程序,可是你却在入口函数的时候使用main而不是WinMain 解 ...
- Spring中@Import注解的使用
Spring中@Import注解的使用 @Import注解算是SpringBoot自动配置原理中一个很重要的注解 认识@Import注解 先看一下源码 @Target(ElementType.TYPE ...
- 数据库和SQL概述
一.数据库的概念 1.DB 数据库(database):存储数据的"仓库".它保存了一系列有组织的数据. 2.DBMS 数据库管理系统(Database Management Sy ...
- C++将数值转换为string
std::to_string string to_string (int val); string to_string (long val); string to_string (long long ...
- java集合-哈希表HashTable
一.简介 HashTable也是一种key-value结构,key-value不允许null,并且这个类的几乎全部的方法都加上了synchronized锁,来保证并发安全,由于加了锁所以性能方面会比较 ...