mirror of
https://github.com/dotnetcore/FreeSql.git
synced 2026-02-04 15:30:53 +08:00
update
22
FluentApi.md
22
FluentApi.md
@@ -1,4 +1,4 @@
|
||||
|
||||
FreeSql 提供使用 Fluent Api, 在外部配置实体的数据库特性,Fluent Api 的方法命名与特性名保持一致,如下:
|
||||
|
||||
```csharp
|
||||
fsql.CodeFirst
|
||||
@@ -12,11 +12,27 @@ fsql.CodeFirst
|
||||
a.Property(b => b.Id).Name("Id22").IsIdentity(true);
|
||||
a.Property(b => b.name).DbType("varchar(100)").IsNullable(true);
|
||||
});
|
||||
|
||||
//以下为实体类
|
||||
class TestFluenttb1
|
||||
{
|
||||
public int Id { get; set; }
|
||||
public string name { get; set; } = "defaultValue";
|
||||
}
|
||||
|
||||
[Table(Name = "cccccdddwww")]
|
||||
class TestFluenttb2
|
||||
{
|
||||
public int Id { get; set; }
|
||||
public string name { get; set; } = "defaultValue";
|
||||
}
|
||||
```
|
||||
|
||||
最好在程序初始化执行,并且这段配置最好只执行一次,避免性能损耗。
|
||||
> fsql 是一个 IFreeSql 对象
|
||||
|
||||
FluentApi 的命名与特性保持一致,有关说明请移步参考:[《实体特性说明》](https://github.com/2881099/FreeSql/wiki/%e5%ae%9e%e4%bd%93%e7%89%b9%e6%80%a7)
|
||||
> 这段配置尽量只执行一次,避免性能损耗
|
||||
|
||||
参考:[《实体特性说明》](https://github.com/2881099/FreeSql/wiki/%e5%ae%9e%e4%bd%93%e7%89%b9%e6%80%a7)
|
||||
|
||||
> v1.1 增加扩展包 [FreeSql.Extensions.EfCoreFluentApi](https://github.com/2881099/FreeSql/tree/master/Extensions/FreeSql.Extensions.EfCoreFluentApi),方便 EfCore 使用者过渡,使用方法接近 EfCore
|
||||
|
||||
|
||||
2
入门.md
2
入门.md
@@ -1,4 +1,4 @@
|
||||
FreeSql 是一个功能强大的对象关系映射程序(O/RM),支持 .NETCore 2.1+ 或 .NETFramework 4.0+(QQ群:4336577)
|
||||
FreeSql是一个功能强大的 .NET ORM 功能库,支持 .NetFramework 4.0+、.NetCore 2.1+、Xamarin 等支持 NetStandard 所有运行平台。(QQ群:4336577)
|
||||
|
||||
## 模型
|
||||
|
||||
|
||||
@@ -8,12 +8,9 @@ class Topic {
|
||||
[Column(IsIdentity = true, IsPrimary = true)]
|
||||
public int Id { get; set; }
|
||||
public int Clicks { get; set; }
|
||||
public int TestTypeInfoGuid { get; set; }
|
||||
public string Title { get; set; }
|
||||
public DateTime CreateTime { get; set; }
|
||||
}
|
||||
|
||||
ISelect<Topic> select => fsql.Select<Topic>();
|
||||
```
|
||||
|
||||
## 分组聚合
|
||||
|
||||
4
分页查询.md
4
分页查询.md
@@ -12,14 +12,12 @@ class Topic {
|
||||
public string Title { get; set; }
|
||||
public DateTime CreateTime { get; set; }
|
||||
}
|
||||
|
||||
ISelect<Topic> select => fsql.Select<Topic>();
|
||||
```
|
||||
|
||||
## 每页20条数据,查询第1页
|
||||
|
||||
```csharp
|
||||
var sql = select.Page(1, 20).ToSql();
|
||||
var sql = fsql.Select<Topic>().Page(1, 20).ToSql();
|
||||
///SELECT a.`Id`, a.`Clicks`, a.`TestTypeInfoGuid`, a.`Title`, a.`CreateTime`
|
||||
//FROM `tb_topic` a
|
||||
//LIMIT 0,20
|
||||
|
||||
19
单表查询.md
19
单表查询.md
@@ -12,23 +12,27 @@ class Topic {
|
||||
public string Title { get; set; }
|
||||
public DateTime CreateTime { get; set; }
|
||||
}
|
||||
|
||||
ISelect<Topic> select => fsql.Select<Topic>();
|
||||
```
|
||||
|
||||
## 单表
|
||||
```csharp
|
||||
var sql = select.Where(a => a.Id == 10).ToSql();
|
||||
var sql = fsql.Select<Topic>()
|
||||
.Where(a => a.Id == 10)
|
||||
.ToSql();
|
||||
///SELECT a.`Id`, a.`Clicks`, a.`TestTypeInfoGuid`, a.`Title`, a.`CreateTime`
|
||||
//FROM `tb_topic` a
|
||||
//WHERE (a.`Id` = 10)
|
||||
|
||||
sql = select.Where(a => a.Id == 10 && a.Id > 10 || a.Clicks > 100).ToSql();
|
||||
sql = fsql.Select<Topic>()
|
||||
.Where(a => a.Id == 10 && a.Id > 10 || a.Clicks > 100)
|
||||
.ToSql();
|
||||
///SELECT a.`Id`, a.`Clicks`, a.`TestTypeInfoGuid`, a.`Title`, a.`CreateTime`
|
||||
//FROM `tb_topic` a
|
||||
//WHERE (a.`Id` = 10 AND a.`Id` > 10 OR a.`Clicks` > 100)
|
||||
|
||||
sql = select.Where(a => new []{1,2,3}.Contains(a.Id)).ToSql();
|
||||
sql = fsql.Select<Topic>()
|
||||
.Where(a => new []{1,2,3}.Contains(a.Id))
|
||||
.ToSql();
|
||||
//SELECT a.`Id`, a.`Clicks`, a.`TestTypeInfoGuid`, a.`Title`, a.`CreateTime`
|
||||
//FROM `tb_topic` a
|
||||
//WHERE (a.`Id` in (1,2,3))
|
||||
@@ -37,8 +41,9 @@ sql = select.Where(a => new []{1,2,3}.Contains(a.Id)).ToSql();
|
||||
## 巧用AsTable
|
||||
```csharp
|
||||
var sql = fsql.Select<User>()
|
||||
.AsTable((a, b) => "(select * from user where clicks > 10)")
|
||||
.Page(1, 10).ToList()
|
||||
.AsTable((a, b) => "(select * from user where clicks > 10)")
|
||||
.Page(1, 10)
|
||||
.ToList()
|
||||
```
|
||||
> v1.0.1 ISelect 增加 WithSql("select * from user ...") 功能快速代理此方法
|
||||
|
||||
|
||||
62
多表查询.md
62
多表查询.md
@@ -24,15 +24,14 @@ class TestTypeParentInfo {
|
||||
public int Id { get; set; }
|
||||
public string Name { get; set; }
|
||||
}
|
||||
|
||||
ISelect<Topic> select => fsql.Select<Topic>();
|
||||
```
|
||||
|
||||
## 1、导航属性联表
|
||||
```csharp
|
||||
sql = select
|
||||
.LeftJoin(a => a.Type.Guid == a.TestTypeInfoGuid)
|
||||
.LeftJoin(a => a.Type.Parent.Id == a.Type.ParentId).ToSql();
|
||||
sql = fsql.Select<Topic>()
|
||||
.LeftJoin(a => a.Type.Guid == a.TestTypeInfoGuid)
|
||||
.LeftJoin(a => a.Type.Parent.Id == a.Type.ParentId)
|
||||
.ToSql();
|
||||
//SELECT a.`Id`, a.`Clicks`, a.`TestTypeInfoGuid`, a__Type.`Guid`, a__Type.`ParentId`, a__Type.`Name`, a.`Title`, a.`CreateTime`
|
||||
//FROM `tb_topic` a
|
||||
//LEFT JOIN `TestTypeInfo` a__Type ON a__Type.`Guid` = a.`TestTypeInfoGuid`
|
||||
@@ -43,7 +42,9 @@ sql = select
|
||||
|
||||
## 2、普通联表
|
||||
```csharp
|
||||
sql = select.LeftJoin<TestTypeInfo>((a, b) => b.Guid == a.TestTypeInfoGuid).ToSql();
|
||||
sql = fsql.Select<Topic>()
|
||||
.LeftJoin<TestTypeInfo>((a, b) => b.Guid == a.TestTypeInfoGuid)
|
||||
.ToSql();
|
||||
//SELECT a.`Id`, a.`Clicks`, a.`TestTypeInfoGuid`, b.`Guid`, b.`ParentId`, b.`Name`, a.`Title`, a.`CreateTime`
|
||||
//FROM `tb_topic` a
|
||||
//LEFT JOIN `TestTypeInfo` b ON b.`Guid` = a.`TestTypeInfoGuid`
|
||||
@@ -51,14 +52,16 @@ sql = select.LeftJoin<TestTypeInfo>((a, b) => b.Guid == a.TestTypeInfoGuid).ToSq
|
||||
|
||||
## 3、复杂联表
|
||||
```csharp
|
||||
sql = select.From<TestTypeInfo, TestTypeParentInfo>((s, b, c) => s
|
||||
.LeftJoin(a => a.TestTypeInfoGuid == b.Guid)
|
||||
.LeftJoin(a => b.ParentId == c.Id)).ToSql();
|
||||
sql = fsql.Select<Topic>().From<TestTypeInfo, TestTypeParentInfo>((s, b, c) => s
|
||||
.LeftJoin(a => a.TestTypeInfoGuid == b.Guid)
|
||||
.LeftJoin(a => b.ParentId == c.Id))
|
||||
.ToSql();
|
||||
|
||||
//或者
|
||||
sql = fsql.Select<Topic, TestTypeInfo, TestTypeParentInfo>()
|
||||
.LeftJoin((a,b,c) => a.TestTypeInfoGuid == b.Guid)
|
||||
.LeftJoin((a,b,c) => b.ParentId == c.id).ToSql();
|
||||
.LeftJoin((a,b,c) => a.TestTypeInfoGuid == b.Guid)
|
||||
.LeftJoin((a,b,c) => b.ParentId == c.id)
|
||||
.ToSql();
|
||||
//SELECT a.`Id`, a.`Clicks`, a.`TestTypeInfoGuid`, b.`Guid`, b.`ParentId`, b.`Name`, a.`Title`, a.`CreateTime`
|
||||
//FROM `tb_topic` a
|
||||
//LEFT JOIN `TestTypeInfo` b ON a.`TestTypeInfoGuid` = b.`Guid`
|
||||
@@ -67,7 +70,9 @@ sql = fsql.Select<Topic, TestTypeInfo, TestTypeParentInfo>()
|
||||
|
||||
## 4、SQL联表
|
||||
```csharp
|
||||
sql = select.LeftJoin("TestTypeInfo b on b.Guid = a.TestTypeInfoGuid and b.Name = ?bname", new { bname = "xxx" }).ToSql();
|
||||
sql = fsql.Select<Topic>()
|
||||
.LeftJoin("TestTypeInfo b on b.Guid = a.TestTypeInfoGuid and b.Name = ?bname", new { bname = "xxx" })
|
||||
.ToSql();
|
||||
//SELECT a.`Id`, a.`Clicks`, a.`TestTypeInfoGuid`, a.`Title`, a.`CreateTime`
|
||||
//FROM `tb_topic` a
|
||||
//LEFT JOIN TestTypeInfo b on b.Guid = a.TestTypeInfoGuid and b.Name = ?bname
|
||||
@@ -75,7 +80,9 @@ sql = select.LeftJoin("TestTypeInfo b on b.Guid = a.TestTypeInfoGuid and b.Name
|
||||
|
||||
## 5、子表Exists
|
||||
```csharp
|
||||
var list2 = select.Where(a => select.As("b").Where(b => b.Id == a.Id).Any()).ToList();
|
||||
var list2 = fsql.Select<Topic>()
|
||||
.Where(a => fsql.Select<Topic>().As("b").Where(b => b.Id == a.Id).Any())
|
||||
.ToList();
|
||||
// SELECT a.`Id`, a.`TypeGuid`, a.`Title`, a.`CreateTime`
|
||||
// FROM `xxx` a
|
||||
// WHERE (exists(SELECT 1
|
||||
@@ -88,7 +95,9 @@ var list2 = select.Where(a => select.As("b").Where(b => b.Id == a.Id).Any()).ToL
|
||||
## 6、子表In
|
||||
|
||||
```csharp
|
||||
var list2 = select.Where(a => select.As("b").ToList(b => b.Id).Contains(a.Id)).ToList();
|
||||
var list2 = fsql.Select<Topic>()
|
||||
.Where(a => fsql.Select<Topic>().As("b").ToList(b => b.Id).Contains(a.Id))
|
||||
.ToList();
|
||||
// SELECT a.`Id`, a.`Clicks`, a.`TypeGuid`, a.`Title`, a.`CreateTime`
|
||||
// FROM `tb_topic` a
|
||||
// WHERE (((cast(a.`Id` as char)) in (SELECT b.`Title`
|
||||
@@ -97,14 +106,15 @@ var list2 = select.Where(a => select.As("b").ToList(b => b.Id).Contains(a.Id)).T
|
||||
|
||||
## 7、子表First/Count/Sum/Max/Min/Avg
|
||||
```csharp
|
||||
var subquery = select.ToSql(a => new {
|
||||
all = a,
|
||||
first = fsql.Select<Child>().Where(b => b.ParentId == a.Id).First(b => b.Id),
|
||||
count = fsql.Select<Child>().Where(b => b.ParentId == a.Id).Count(),
|
||||
sum = fsql.Select<Child>().Where(b => b.ParentId == a.Id).Sum(b => b.Score),
|
||||
max = fsql.Select<Child>().Where(b => b.ParentId == a.Id).Max(b => b.Score),
|
||||
min = fsql.Select<Child>().Where(b => b.ParentId == a.Id).Min(b => b.Score),
|
||||
avg = fsql.Select<Child>().Where(b => b.ParentId == a.Id).Avg(b => b.Score)
|
||||
var subquery = fsql.Select<Topic>().ToSql(a => new
|
||||
{
|
||||
all = a,
|
||||
first = fsql.Select<Child>().Where(b => b.ParentId == a.Id).First(b => b.Id),
|
||||
count = fsql.Select<Child>().Where(b => b.ParentId == a.Id).Count(),
|
||||
sum = fsql.Select<Child>().Where(b => b.ParentId == a.Id).Sum(b => b.Score),
|
||||
max = fsql.Select<Child>().Where(b => b.ParentId == a.Id).Max(b => b.Score),
|
||||
min = fsql.Select<Child>().Where(b => b.ParentId == a.Id).Min(b => b.Score),
|
||||
avg = fsql.Select<Child>().Where(b => b.ParentId == a.Id).Avg(b => b.Score)
|
||||
});
|
||||
```
|
||||
|
||||
@@ -112,16 +122,16 @@ var subquery = select.ToSql(a => new {
|
||||
|
||||
```csharp
|
||||
fsql.Select<TestTypeInfo>()
|
||||
.Where(a => a.Topics.AsSelect().Any(b => b.Title.Contains("xx")))
|
||||
.ToSql();
|
||||
.Where(a => a.Topics.AsSelect().Any(b => b.Title.Contains("xx")))
|
||||
.ToSql();
|
||||
```
|
||||
|
||||
效果等同于:
|
||||
|
||||
```csharp
|
||||
fsql.Select<TestTypeInfo>()
|
||||
.Where(a => fsql.Select<Topic>().Any(b => b.Title.Contains("xx")))
|
||||
.ToSql();
|
||||
.Where(a => fsql.Select<Topic>().Any(b => b.Title.Contains("xx")))
|
||||
.ToSql();
|
||||
```
|
||||
|
||||
将集合属性快速转换为 ISelect 进行子查询操作。
|
||||
|
||||
2
延时加载.md
2
延时加载.md
@@ -27,7 +27,7 @@ public class OrderDetail {
|
||||
> 延时加载功能,依赖 FreeSql.Extensions.LazyLoading 包,请前往 nuget 下载;
|
||||
|
||||
```csharp
|
||||
IFreeSql fsql = new FreeSql.FreeSqlBuilder()
|
||||
static IFreeSql fsql = new FreeSql.FreeSqlBuilder()
|
||||
.UseConnectionString(FreeSql.DataType.MySql, "Data Source=127.0.0.1;Port=3306;User ID=root;Password=root;Initial Catalog=cccddd;Charset=utf8;SslMode=none;Max pool size=10")
|
||||
.UseLazyLoading(true) //开启延时加载功能
|
||||
.UseMonitorCommand(
|
||||
|
||||
2
租户.md
2
租户.md
@@ -41,7 +41,7 @@ LEFT JOIN t2 on ... AND (t2.IsDeleted = 0)
|
||||
WHERE t1.IsDeleted = 0
|
||||
```
|
||||
|
||||
其中的实体可附加表达式时才生效,支持子表查询。单次查询使用的表数目越多收益越大。
|
||||
实体可附加表达式时才生效,支持子表查询。单次查询使用的表数目越多收益越大。
|
||||
|
||||
可应用范围:
|
||||
|
||||
|
||||
2
自定义特性.md
2
自定义特性.md
@@ -22,6 +22,8 @@ class ModelAopConfigEntity {
|
||||
}
|
||||
```
|
||||
|
||||
> v1.1 增加扩展包 [FreeSql.Extensions.EfCoreFluentApi](https://github.com/2881099/FreeSql/tree/master/Extensions/FreeSql.Extensions.EfCoreFluentApi),方便 EfCore 使用者过渡,使用方法接近 EfCore
|
||||
|
||||
## 优先级
|
||||
|
||||
数据库特性 > 实体特性 > FluentApi(配置特性) > Aop(配置特性)
|
||||
|
||||
20
表达式函数.md
20
表达式函数.md
@@ -83,20 +83,20 @@ var t4 = fsql.Select<T>()
|
||||
[ExpressionCall]
|
||||
public static class DbFunc
|
||||
{
|
||||
//必要定义 static + ThreadLocal
|
||||
static ThreadLocal<ExpressionCallContext> context = new ThreadLocal<ExpressionCallContext>();
|
||||
//必要定义 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.Sqlite) //重写内容
|
||||
context.Value.Result = $"date_format({up.ParsedContent["that"]}, {up.ParsedContent["arg1"]})";
|
||||
return that;
|
||||
}
|
||||
public static DateTime FormatDateTime(this DateTime that, string arg1)
|
||||
{
|
||||
var up = context.Value;
|
||||
if (up.DataType == FreeSql.DataType.Sqlite) //重写内容
|
||||
up.Result = $"date_format({up.ParsedContent["that"]}, {up.ParsedContent["arg1"]})";
|
||||
return that;
|
||||
}
|
||||
}
|
||||
|
||||
var sql1 = fsql.Select<SysModule>()
|
||||
.ToSql(a => a.CreateTime.FormatDateTime("yyyy-MM-dd"));
|
||||
.ToSql(a => a.CreateTime.FormatDateTime("yyyy-MM-dd"));
|
||||
//SELECT date_format(a."CreateTime", 'yyyy-MM-dd') as1
|
||||
//FROM "SysModule" a
|
||||
```
|
||||
|
||||
5
读写分离.md
5
读写分离.md
@@ -23,8 +23,9 @@ static IFreeSql fsql = new FreeSql.FreeSqlBuilder()
|
||||
.UseSlave("connectionString1", "connectionString2") //使用从数据库,支持多个
|
||||
.Build(); //请务必定义成 Singleton 单例模式
|
||||
|
||||
select.Where(a => a.Id == 1).ToOne(); //读【从库】(默认)
|
||||
select.Master().WhereId(a => a.Id == 1).ToOne(); //强制读【主库】
|
||||
fsql.Select<T>().Where(a => a.Id == 1).ToOne(); //读【从库】(默认)
|
||||
|
||||
fsql.Select<T>().Master().WhereId(a => a.Id == 1).ToOne(); //强制读【主库】
|
||||
```
|
||||
|
||||
## 参考资料
|
||||
|
||||
49
骚操作.md
49
骚操作.md
@@ -173,7 +173,7 @@ LEFT JOIN t2 on ... AND (t2.IsDeleted = 0)
|
||||
WHERE t1.IsDeleted = 0
|
||||
```
|
||||
|
||||
其中的实体可附加表达式时才生效,支持子表查询。单次查询使用的表数目越多收益越大。
|
||||
实体可附加表达式时才生效,支持子表查询。单次查询使用的表数目越多收益越大。
|
||||
|
||||
---
|
||||
|
||||
@@ -249,49 +249,22 @@ SaveMany【多对多】的机制规则与联级保存的一样,如下:
|
||||
[ExpressionCall]
|
||||
public static class DbFunc
|
||||
{
|
||||
//必要定义 static + ThreadLocal
|
||||
static ThreadLocal<ExpressionCallContext> context = new ThreadLocal<ExpressionCallContext>();
|
||||
//必要定义 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.Sqlite) //重写内容
|
||||
context.Value.Result = $"date_format({up.ParsedContent["that"]}, {up.ParsedContent["arg1"]})";
|
||||
return that;
|
||||
}
|
||||
|
||||
public static string SetDbParameter(this string that, int size)
|
||||
{
|
||||
if (context.Value.DbParameter != null)
|
||||
{
|
||||
//已经参数化了,直接修改长度
|
||||
//提示:此条件可能开启了全局表达式参数化功能 UseGenerateCommandParameterWithLambda(true)
|
||||
context.Value.DbParameter.Size = size;
|
||||
return that;
|
||||
}
|
||||
var guid = Guid.NewGuid().ToString("N").ToLower();
|
||||
context.Value.UserParameters.Add(new SqlParameter
|
||||
{
|
||||
ParameterName = guid,
|
||||
SqlDbType = System.Data.SqlDbType.VarChar,
|
||||
Size = size,
|
||||
Value = that
|
||||
});
|
||||
return $"@{guid}"; //重写内容
|
||||
}
|
||||
public static DateTime FormatDateTime(this DateTime that, string arg1)
|
||||
{
|
||||
var up = context.Value;
|
||||
if (up.DataType == FreeSql.DataType.Sqlite) //重写内容
|
||||
up.Result = $"date_format({up.ParsedContent["that"]}, {up.ParsedContent["arg1"]})";
|
||||
return that;
|
||||
}
|
||||
}
|
||||
|
||||
var sql1 = fsql.Select<SysModule>()
|
||||
.ToSql(a => a.CreateTime.FormatDateTime("yyyy-MM-dd"));
|
||||
.ToSql(a => a.CreateTime.FormatDateTime("yyyy-MM-dd"));
|
||||
//SELECT date_format(a."CreateTime", 'yyyy-MM-dd') as1
|
||||
//FROM "SysModule" a
|
||||
|
||||
var sql2 = fsql.Select<SysModule>()
|
||||
.Where(a => a.Title == "123123".SetDbParameter(20))
|
||||
.ToSql();
|
||||
//SELECT ...
|
||||
//FROM [SysModule] a
|
||||
//WHERE (a.[Title] = @6a8b79d7001540369a2f52ecbba15679)
|
||||
```
|
||||
|
||||
\[ExpressionCall\] 特性可在静态扩展类上标记,也可以在单个静态方法上标记;
|
||||
|
||||
Reference in New Issue
Block a user