一、前言
Fast Framework 基于NET6.0 封装的轻量级 ORM 框架 支持多种数据库 SqlServer Oracle MySql PostgreSql Sqlite
优点:体积小、可动态切换不同实现类库、原生支持微软特性、流畅API、使用简单、性能高、模型数据绑定采用 委托、强大的表达式解析、支持多种子查询可实现较为复杂查询、源代码可读性强。
缺点:目前仅支持Db Frist Code Frist 后续迭代。
开源地址 https://github.com/China-Mr-zhong/Fast.Framework (唯一)
目前作者已使用该框架应用多个生产项目
个别亮点功能:数值类型绑定自动格式化小数点后面多余的0、表达式参数名称自动编排 无需强制统一参数名称
本作者不提供任何性能对比数据,请各位感兴趣的自行测试,对比前建议预热连接
二、项目明细
名称 | 说明 |
---|---|
Fast.Framework | 框架主项目 |
Fast.Framework.Logging | 基于微软接口实现的文件日志(非必要可不引用) |
Fast.Framework.Test | 控制台测试项目 |
Fast.Framework.UnitTest | 单元测试项目 |
Fast.Framework.Web.Test | Web测试项目 |
三、核心对象
Ado 原生Ado对象
代码语言:javascript复制 IAdo ado = new AdoProvider(new DbOptions()
{
DbId = "1",
DbType = DbType.MySQL,
ProviderName = "MySqlConnector",
FactoryName = "MySqlConnector.MySqlConnectorFactory,MySqlConnector",
ConnectionStrings = "server=localhost;database=Test;user=root;pwd=123456789;port=3306;min pool size=3;max pool size=100;connect timeout=30;"
});
DbContext 支持多租户 支持切换不同Ado实现类库 设置 ProviderName和FactoryName 即可
代码语言:javascript复制 IDbContext db = new DbContext(new List<DbOptions>() {
new DbOptions()
{
DbId = "1",
DbType = DbType.MySQL,
ProviderName = "MySqlConnector",
FactoryName = "MySqlConnector.MySqlConnectorFactory,MySqlConnector",
ConnectionStrings = "server=localhost;database=Test;user=root;pwd=123456789;port=3306;min pool size=3;max pool size=100;connect timeout=30;"
}});
DbOptions Json文件配置格式
代码语言:javascript复制"DbOptions": [
{
"DbId": 1,
"DbType": "SQLServer",
"ProviderName": "System.Data.SqlClient",
"FactoryName": "System.Data.SqlClient.SqlClientFactory,System.Data",
"ConnectionStrings": "server=localhost;database=Test;user=sa;pwd=123456789;min pool size=3;max pool size=100;connect timeout=120;"
}]
主从分离(读写分离)配置
代码语言:javascript复制 "DbOptions": [
{
"DbId": 2,
"DbType": "MySQL",
"IsDefault": true,
"ProviderName": "MySqlConnector",
"FactoryName": "MySqlConnector.MySqlConnectorFactory,MySqlConnector",
"ConnectionStrings": "server=localhost;database=Test;user=root;pwd=123456789;port=3306;min pool size=0;max pool size=100;connect timeout=120;AllowLoadLocalInfile=true;",
"UseMasterSlaveSeparation": true,//使用主从分离 注意所有事务将强制走主库
"SlaveItems": [
{
"Weight": 1,//注意多个从库 必须配置权重且总权重>从库数
"ConnectionStrings": "server=localhost;database=Test1;user=root;pwd=123456789;port=3306;min pool size=0;max pool size=100;connect timeout=120;AllowLoadLocalInfile=true;",
"Description": "从库连接配置"
},
{
"Weight": 2,
"ConnectionStrings": "server=localhost;database=Test2;user=root;pwd=123456789;port=3306;min pool size=0;max pool size=100;connect timeout=120;AllowLoadLocalInfile=true;",
"Description": "从库连接配置"
}
],
"Description": "主库连接配置"
}
]
Asp.net Core 依赖注入
代码语言:javascript复制// 注册服务
var builder = WebApplication.CreateBuilder(args);
// 添加数据库上下文
builder.Services.AddFastDbContext();
// 从Json配置文件加载数据库选项
builder.Services.Configure<List<DbOptions>>(builder.Configuration.GetSection("DbOptions"));
// 产品服务类 通过构造方法注入
public class ProductService
{
/// <summary>
/// 数据库
/// </summary>
private readonly IDbContext db;
/// <summary>
/// 构造方法
/// </summary>
/// <param name="db">数据库</param>
public ProductService(IDbContext db)
{
this.db = db;
}
}
四、插入
实体对象插入
代码语言:javascript复制 var product = new Product()
{
ProductCode = "1001",
ProductName = "测试商品1"
};
var result = db.Insert(product).Exceute();
Console.WriteLine($"实体对象插入 受影响行数 {result}");
实体对象插入并返回自增ID 仅支持 SQLServer MySQL SQLite
代码语言:javascript复制 var product = new Product()
{
ProductCode = "1001",
ProductName = "测试产品1"
};
var result = db.Insert(product).ExceuteReturnIdentity();
Console.WriteLine($"实体对象插入 返回自增ID {result}");
实体对象列表插入
代码语言:javascript复制 var list = new List<Product>();
for (int i = 0; i < 2100; i )
{
list.Add(new Product()
{
ProductCode = $"编号{i 1}",
ProductName = $"名称{i 1}"
});
}
var result = db.Insert(list).Exceute();
Console.WriteLine($"实体对象列表插入 受影响行数 {result}");
匿名对象插入
代码语言:javascript复制 var obj = new
{
ProductCode = "1001",
ProductName = "测试商品1"
};
//注意:需要使用As方法显示指定表名称
var result = db.Insert(obj).As("Product").Exceute();
Console.WriteLine($"匿名对象插入 受影响行数 {result}");
匿名对象列表插入
代码语言:javascript复制 var list = new List<object>();
for (int i = 0; i < 2100; i )
{
list.Add(new
{
ProductCode = $"编号{i 1}",
ProductName = $"名称{i 1}"
});
}
//注意:需要使用As方法显示指定表名称
var result = db.Insert(list).As("Product").Exceute();
Console.WriteLine($"匿名对象列表插入 受影响行数 {result}");
字典插入
代码语言:javascript复制 var product = new Dictionary<string, object>()
{
{"ProductCode","1001"},
{ "ProductName","测试商品1"}
};
var result = db.Insert(product).As("Product").Exceute();
Console.WriteLine($"字典插入 受影响行数 {result}");
字典列表插入
代码语言:javascript复制 var list = new List<Dictionary<string, object>>();
for (int i = 0; i < 2100; i )
{
list.Add(new Dictionary<string, object>()
{
{"ProductCode","1001"},
{ "ProductName","测试商品1"}
});
}
var result = db.Insert(list).As("Product").Exceute();
Console.WriteLine($"字典列表插入 受影响行数 {result}");
五、删除
实体对象删除
代码语言:javascript复制 var product = new Product()
{
ProductId = 1,
ProductCode = "1001",
ProductName = "测试商品1"
};
//注意:必须标记KeyAuttribute特性 否则将抛出异常
var result = db.Delete(product).Exceute();
Console.WriteLine($"实体删除 受影响行数 {result}");
无条件删除
代码语言:javascript复制 var result = db.Delete<Product>().Exceute();
Console.WriteLine($"无条件删除 受影响行数 {result}");
表达式删除
代码语言:javascript复制 var result = await db.Delete<Product>().Where(w => w.ProductId == 1).ExceuteAsync();
Console.WriteLine($"条件删除 受影响行数 {result}");
特殊删除
代码语言:javascript复制 //特殊用法 如需单个条件或多个可搭配 WhereColumn或WhereColumns方法
var result = await db.Delete<object>().As("Product").ExceuteAsync();
Console.WriteLine($"无实体删除 受影响行数 {result}");
六、更新
实体对象更新
代码语言:javascript复制 var product = new Product()
{
ProductId = 1,
ProductCode = "1001",
ProductName = "测试商品1"
};
//注意:标记KeyAuttribute特性属性或使用Where条件,为了安全起见全表更新将必须使用Where方法
var result = db.Update(product).Exceute();
Console.WriteLine($"对象更新 受影响行数 {result}");
指定列更新
代码语言:javascript复制 var result = db.Update<Product>(new Product() { ProductCode = "1001", ProductName = "1002" }).Columns("ProductCode", "ProductName").Exceute();
// 字段很多的话可以直接new List<string>(){"列1","列2"}
忽略列更新
代码语言:javascript复制 var result = db.Update<Product>(new Product() { ProductCode = "1001", ProductName = "1002" }).IgnoreColumns("Custom1").Exceute();
// 同上使用方法一样
实体对象列表更新
代码语言:javascript复制 var list = new List<Product>();
for (int i = 0; i < 2022; i )
{
list.Add(new Product()
{
ProductCode = $"编号{i 1}",
ProductName = $"名称{i 1}"
});
}
//注意:标记KeyAuttribute特性属性或使用WhereColumns方法指定更新条件列
var result = db.Update(list).Exceute();
Console.WriteLine($"对象列表更新 受影响行数 {result}");
匿名对象更新
代码语言:javascript复制 var obj = new
{
ProductId = 1,
ProductCode = "1001",
ProductName = "测试商品1"
};
//注意:需要显示指定表名称 以及更新条件 使用 Where或者WhereColumns方法均可
var result = db.Update(obj).As("product").WhereColumns("ProductId").Exceute();
Console.WriteLine($"匿名对象更新 受影响行数 {result}");
匿名对象列表更新
代码语言:javascript复制 var list = new List<object>();
for (int i = 0; i < 2022; i )
{
list.Add(new
{
ProductId = i 1,
ProductCode = $"编号{i 1}",
ProductName = $"名称{i 1}"
});
}
//由于是匿名对象需要显示指定表名称,使用WhereColumns方法指定更新条件列
var result = db.Update(list).As("Product").WhereColumns("ProductId").Exceute();
Console.WriteLine($"匿名对象列表更新 受影响行数 {result}");
字典更新
代码语言:javascript复制 var product = new Dictionary<string, object>()
{
{ "ProductId",1},
{"ProductCode","1001"},
{ "ProductName","测试商品1"}
};
var result = db.Update(product).As("Product").WhereColumns("ProductId").Exceute();
Console.WriteLine($"字典更新 受影响行数 {result}");
字典列表更新
代码语言:javascript复制 var list = new List<Dictionary<string, object>>();
for (int i = 0; i < 2022; i )
{
list.Add(new Dictionary<string, object>()
{
{ "ProductId",i 1},
{"ProductCode",$"更新编号:{i 1}"},
{ "ProductName",$"更新商品:{i 1}"}
});
}
var result = db.Update(list).As("Product").WhereColumns("ProductId").Exceute();
Console.WriteLine($"字典列表更新 受影响行数 {result}");
指定条件更新
代码语言:javascript复制 var product = new Product()
{
ProductId = 1,
ProductCode = "1001",
ProductName = "测试商品1"
};
var result = db.Update(product).Where(p => p.ProductId == 100).Exceute();
Console.WriteLine($"表达式更新 受影响行数 {result}");
并发更新 乐观锁-版本控制
代码语言:javascript复制 //注意:仅支持非列表更新 版本列数据类型仅支持 object、string、Guid 时间类型存在精度丢失所以不做支持
var obj = db.Query<Product>().Where(w => w.ProductId == 1).Frist();
obj.Custom1 = "测试版本控制修改";
//参数为 true 更新失败将抛出异常
var result = db.Update(obj).ExceuteWithOptLock(true);
七、查询
单一查询
代码语言:javascript复制 var data = db.Query<Product>().First();
列表查询
代码语言:javascript复制 var data = db.Query<Product>().ToList();
返回单个字典
代码语言:javascript复制 var data = db.Query<Product>().ToDictionary();
返回字典列表
代码语言:javascript复制 var data = db.Query<Product>().ToDictionaryList();
分页查询
代码语言:javascript复制 //分页查询不返回总数
var data = db.Query<Product>().ToPageList(1,100);
//分页查询返回总数
var total = 0;//定义总数变量
var data = db.Query<Product>().ToPageList(1, 1, ref total);
Console.WriteLine($"总数:{total}");
计数查询
代码语言:javascript复制 var data = db.Query<Product>().Count();
任何查询
代码语言:javascript复制 var data = db.Query<Product>().Any();
条件查询
代码语言:javascript复制 var data = db.Query<Product>().Where(w => w.ProductId == 1).ToList;
Like 查询
代码语言:javascript复制 var data = db.Query<Product>().Where(w => w.ProductName.StartsWith("左模糊") || w.ProductName.EndsWith("右模糊") || w.ProductName.Contains("全模糊")).ToList();
Not Like查询
代码语言:javascript复制var data = db.Query<Product>().Where(w => !w.ProductName.StartsWith("左模糊") || !w.ProductName.EndsWith("右模糊") || !w.ProductName.Contains("全模糊")).ToList();
Select查询 (选择字段)
代码语言:javascript复制 var data = db.Query<Product>().Select(s => new
{
s.ProductId,
s.ProductName
}).ToList();
Select查询 (Case When)
代码语言:javascript复制 var data = db.Query<Product>().Select(s => new
{
CaseTest1 = SqlFunc.Case(s.Custom1).When("1").Then("xx1").When("2").Then("xx2").Else("xx3").End(),
CaseTest2 = SqlFunc.CaseWhen<string>(s.Custom1 == "1").Then("xx1").When(s.Custom1 == "2").Then("xx2").Else("xx3").End()
}).ToList();
分组查询
代码语言:javascript复制 var data = db.Query<Product>().GroupBy(s => new
{
s.ProductId,
s.ProductName
}).ToList();
分组聚合查询
代码语言:javascript复制 var sql = db.Query<Order>().InnerJoin<OrderDetail>((a, b) => a.OrderId == b.OrderId).GroupBy((a, b) => new
{
a.OrderCode
}).Select((a, b) => new
{
a.OrderCode,
Sum_Qty = SqlFunc.Sum(b.Qty)//支持嵌套
}).ToList();
排序查询
代码语言:javascript复制 var data = db.Query<Product>().OrderBy(s => new
{
s.CreateTime
}).ToList();
//这是多个字段排序使用方法 还有其它重载方法
Having查询
代码语言:javascript复制 var data = db.Query<Product>().GroupBy(s => new
{
s.ProductId,
s.ProductName
}).Having(s => SqlFunc.Count(s.ProductId) > 1).ToList();
//必须先使用GroupBy方法 懂得都懂
联表查询
代码语言:javascript复制 var data = db.Query<Product>().LeftJoin<Class1>((a, b) => a.ProductId == b.ProductId).ToList();
// 右连接 RightJoin 内连接 InnerJoin 全连接 FullJoin
联合查询
代码语言:javascript复制 var query1 = db.Query<Product>();
var query2 = db.Query<Product>();
db.Union(query1, query2);//联合
db.UnionAll(query1, query2);//全联合
//执行查询调用Toxx方法
查询并插入 仅支持同实例的数据库 跨库 个人还是建议 用事务分开写查询和插入
代码语言:javascript复制 //方式1
var result1 = db.Query<Product>().Where(w => w.ProductId == 1489087).Select(s => new
{
s.ProductCode,
s.ProductName
}).Insert<Product>(p => new
{
p.ProductCode,
p.ProductName
});
//方式2 需要注意的是 显示指定不带 列标识符 例如 `列名称1` 如有字段冲突 可自行加上标识符
var result2 = db.Query<Product>().Where(w => w.ProductId == 1489087).Select(s => new
{
s.ProductCode,
s.ProductName
}).Insert("表名称 同实例不同库 可以使用 db.数据库名称.表名称 ", "列名称1", "列名称2", "`带标识的列名称3`");
//方式3 需要注意同方式2 一样
var result3 = db.Query<Product>().Where(w => w.ProductId == 1489087).Select(s => new
{
s.ProductCode,
s.ProductName
}).Insert("表名称 同实例不同库 可以使用 db.数据库名称.表名称 ", new List<string>() { "列名称1" });
In查询
代码语言:javascript复制 // 方式1
var data1 = db.Query<Product>().Where(w => SqlFunc.In(w.ProductCode, "1001", "1002")).ToList();
// 方式2
var data2 = db.Query<Product>().Where(w => SqlFunc.In(w.ProductCode, new List<string>() { "123", "456" })).ToList();
// 方式3 需要动态更新IN值 使用这种
var list = new List<string>() { "123", "456" };
var data3 = db.Query<Product>().Where(w => SqlFunc.In(w.ProductCode, list)).ToList();
// 方法4 参数同上一样 单独分离IN和NotIN 是为了兼容匿名查询
var data4 = db.Query<Product>().In("字段名称", "1001", "1002").ToList();
Select子查询
代码语言:javascript复制 var subQuery = db.Query<Product>().Where(w => w.ProductId == 1).Select(s => s.ProductName);
var sql1 = db.Query<Product>().Select(s => new Product()
{
Custom1 = db.SubQuery<string>(subQuery)// SubQuery 的泛型是根据你左边赋值的属性类型来定义
}).ToList();
// 这种没有使用new 的 泛型可随意定义 实际作用就是避免 对象属性赋值类型冲突的问题
var sql2 = db.Query<Product>().Select(s => db.SubQuery<string>(subQuery)).ToList();
From子查询
代码语言:javascript复制 var subQuery = db.Query<Product>();
var data = db.Query(subQuery).OrderBy(o => o.ProductCode).ToList();
Join子查询
代码语言:javascript复制 var subQuery = db.Query<Product>();
var data = db.Query<Product>().InnerJoin(subQuery, (a, b) => a.ProductId == b.ProductId).ToList();
Include查询
代码语言:javascript复制 // 联表条件 默认优先匹配主键 其次带有ID结尾的名称
var data = db.Query<Category>().Include(i => i.Products).ToList();
八、Lambda表达式
动态表达式 命名空间 Fast.Framework.Utils
代码语言:javascript复制 var ex = DynamicWhereExp.Create<Product>().AndIF(1 == 1, a => a.DeleteMark == true).Build();
var data = db.Query<Product>().Where(ex).ToList();
Sql函数 自定义函数 需引入命名空间 Fast.Framework.Utils
- 类型转换 方法名称解析示例值说明自定义函数ToStringCAST(a.[xx] AS TEXT )转换 TEXT否ToDateTimeDATETIME( a.[xx] )转换 DateTime否ToDecimalCAST(a.[xx] AS DECIMAL(10,6) )转换 DECIMAL否ToDoubleCAST(a.[xx] AS NUMERIC(10,6) )转换 NUMERIC否ToSingleCAST(a.[xx] AS FLOAT )转换 FLOAT否ToInt32CAST(a.[xx] AS INTEGER )转换 INTEGER否ToInt64CAST(a.[xx] AS BIGINT )转换 BIGINT否ToBooleanCAST(a.[xx] AS CHAR(1) )转换 CHAR否ToCharCAST(a.[xx] AS CHAR(2) )转换 CHAR否
- 聚合函数 方法名称解析示例值说明自定义函数MaxMAX( a.[xx] )最大值是MinMIN( a.[xx] )最小值是CountCOUNT( a.[xx] )计数是SumSUM( a.[xx] )合计是AvgAVG( a.[xx] )平均是
- 数学函数 方法名称解析示例值说明自定义函数AbsABS( a.[xx] )绝对值是RoundROUND( a.[xx] ,2 )四舍五入是
- 字符串函数 方法名称解析示例值说明自定义函数StartsWithLIKE '%'||'xx'左模糊否EndsWithLIKE 'xx'||'%'右模糊否ContainsLIKE '%'||'xx'||'%'全模糊否SubStringSUBSTRING( 'xxxxxx' ,1,3 )截取否ReplaceREPLACE( 'xxx','x','y' )替换否LengthLENGTH( 'xxx' )长度是TrimTRIM( ' xx ' )修剪空格否TrimStartLTRIM( ' xx ' )修剪起始空格否TrimEndRTRIM( ' xx ' )修剪末尾空格否ToUpperUPPER( 'xx' )大写否ToLowerLOWER( 'xx' )小写否
- 日期函数 方法名称解析示例值说明自定义函数AddYearsDATETIME( a.[xx],'1 YEAR' )添加年份否AddMonthsDATETIME( a.[xx],'1 MONTH' )添加月份否AddDaysDATETIME( a.[xx],'1 DAY' )添加天数否AddHoursDATETIME( a.[xx],'1 HOUR' )添加时否AddMinutesDATETIME( a.[xx],'1 MINUTE' )添加分否AddSecondsDATETIME( a.[xx],'1 SECOND' )添加秒否AddMillisecondsDATETIME( a.[xx],'1 YEAR' )添加毫秒否YearSTRFTIME( '%Y', a.[xx] )获取年份是MonthSTRFTIME( '%m', a.[xx] )获取月份是DaySTRFTIME( '%j', a.[xx] )获取天数是
- 查询函数 方法名称解析示例值说明自定义函数InIN ( a."xx" ,'x1','x2','x3' )In查询是NotInNOT IN ( a."xx" ,'x1','x2','x3' )Not In查询是
- 其它函数 方法名称解析示例值说明自定义函数Equalsp.”ProductCode“ = '123'比较否CaseCASEcase是WhenWHENwhen是ThenTHENthen是ElseELSEelse是EndENDend是
- 类型转换 方法名称解析示例值说明自定义函数ToStringa."xx"::VARCHAR(255)转换 VARCHAR否ToDateTimea."xx"::TIMESTAMP转换 TIMESTAMP否ToDecimala."xx"::DECIMAL(10,6)转换 DECIMAL否ToDoublea."xx"::NUMERIC(10,6)转换 NUMERIC否ToSinglea."xx"::REAL转换 REAL否ToInt32a."xx"::INTEGER转换 INT否ToInt64a."xx"::BIGINT转换 BIGINT否ToBooleana."xx"::BOOLEAN转换 BOOLEAN否ToChara."xx"::CHAR(2)转换 CHAR否
- 聚合函数 方法名称解析示例值说明自定义函数MaxMAX( a."xx" )最大值是MinMIN( a."xx" )最小值是CountCOUNT( a."xx" )计数是SumSUM( a."xx" )合计是AvgAVG( a."xx" )平均是
- 数学函数 方法名称解析示例值说明自定义函数AbsABS( a."xx" )绝对值是RoundROUND( a."xx" ,2 )四舍五入是
- 字符串函数 方法名称解析示例值说明自定义函数StartsWithLIKE CONCAT( '%','xx' )左模糊否EndsWithLIKE CONCAT( 'xx','%' )右模糊否ContainsLIKE CONCAT( '%','xx','%' )全模糊否SubStringSUBSTRING( 'xxxxxx' ,1,3 )截取否ReplaceREPLACE( 'xxx','x','y' )替换否LengthLENGTH( 'xxx' )长度是TrimTRIM( ' xx ' )修剪空格否TrimStartLTRIM( ' xx ' )修剪起始空格否TrimEndRTRIM( ' xx ' )修剪末尾空格否ToUpperUPPER( 'xx' )大写否ToLowerLOWER( 'xx' )小写否ConcatCONCAT(a."xx1",a."xx2")字符串拼接是
- 日期函数 方法名称解析示例值说明自定义函数AddYearsa."xx" INTERVAL '1 YEAR'添加年份否AddMonthsa."xx" INTERVAL '1 MONTH'添加月份否AddDaysa."xx" INTERVAL '1 DAY'添加天数否AddHoursa."xx" INTERVAL '1 HOUR'添加时否AddMinutesa."xx" INTERVAL '1 MINUTE'添加分否AddSecondsa."xx" INTERVAL '1 SECOND'添加秒否AddMillisecondsa."xx" INTERVAL '1 MINUTE_SECOND'添加毫秒否YearYEAR( a."xx" )获取年份是MonthMONTH( a."xx" )获取月份是DayDAY( a."xx" )获取天数是
- 查询函数 方法名称解析示例值说明自定义函数InIN ( a."xx" ,'x1','x2','x3' )In查询是NotInNOT IN ( a."xx" ,'x1','x2','x3' )Not In查询是
- 其它函数 方法名称解析示例值说明自定义函数Equalsp.”ProductCode“ = '123'比较否CaseCASEcase是WhenWHENwhen是ThenTHENthen是ElseELSEelse是EndENDend是
- 类型转换 方法名称解析示例值说明自定义函数ToStringCAST( a."xx" AS VARCHAR(255) )转换 VARCHAR否ToDateTimeTO_TIMESTAMP( a."xx" ,'yyyy-MM-dd hh:mi:ss.ff')转换 DATETIME否ToDecimalCAST( a."xx" AS DECIMAL(10,6) )转换 DECIMAL否ToDoubleCAST( a."xx" AS NUMBER )转换 NUMBER否ToSingleCAST( a."xx" AS FLOAT )转换 FLOAT否ToInt32CAST( a."xx" AS INT )转换 INT否ToInt64CAST( a."xx" AS NUMBER )转换 NUMBER否ToBooleanCAST( a."xx" AS CHAR(1) )转换 CHAR否ToCharCAST( a."xx" AS CHAR(2) )转换 CHAR否
- 聚合函数 方法名称解析示例值说明自定义函数MaxMAX( a."xx" )最大值是MinMIN( a."xx" )最小值是CountCOUNT( a."xx" )计数是SumSUM( a."xx" )合计是AvgAVG( a."xx" )平均是
- 数学函数 方法名称解析示例值说明自定义函数AbsABS( a."xx" )绝对值是RoundROUND( a."xx" ,2 )四舍五入是
- 字符串函数 方法名称解析示例值说明自定义函数StartsWithLIKE CONCAT( '%','xx' )左模糊否EndsWithLIKE CONCAT( 'xx','%' )右模糊否ContainsLIKE CONCAT( '%','xx','%' )全模糊否SubStringSUBSTRING( 'xxxxxx' ,1,3)截取否ReplaceREPLACE( 'xxx','x','y')替换否LengthLENGTH( 'xxx' )长度是TrimStartLTRIM( ' xx ' )修剪起始空格否TrimEndRTRIM( ' xx ' )修剪末尾空格否ToUpperUPPER( 'xx' )大写否ToLowerLOWER( 'xx' )小写否ConcatCONCAT(a."xx1",a."xx2")字符串拼接是
- 日期函数 方法名称解析示例值说明自定义函数YearEXTRACT( YEAR FROM a."xx" )获取年份是MonthEXTRACT( MONTH FROM a."xx" )获取月份是DayEXTRACT( DAY FROM a."xx" )获取天数是
- 查询函数 方法名称解析示例值说明自定义函数InIN ( a."xx" ,'x1','x2','x3')In查询是NotInNOT IN ( a."xx",'x1','x2','x3')Not In查询是
- 其它函数 方法名称解析示例值说明自定义函数Equalsp."ProductCode" = '123'比较否NvlNVL( a."xx",0 )空,默认是CaseCASEcase是WhenWHENwhen是ThenTHENthen是ElseELSEelse是EndENDend是
- 类型转换 方法名称解析示例值说明自定义函数ToStringCAST( a.`xx` AS CHAR(510) )转换 CHAR(510)否ToDateTimeCAST( a.`xx` AS DATETIME )转换 DATETIME否ToDecimalCAST( a.`xx` AS DECIMAL(10,6) )转换 DECIMAL(10,6)否ToDoubleCAST( a.`xx` AS DECIMAL(10,6) )转换 DECIMAL(10,6)否ToInt32CAST( a.`xx` AS DECIMAL(10) )转换 DECIMAL(10)否ToInt64CAST( a.`xx` AS DECIMAL(19) )转换 DECIMAL(19)否ToBooleanCAST( a.`xx` AS UNSIGNED )转换 UNSIGNED否ToCharCAST( a.`xx` AS CHAR(2) )转换 CHAR(2)否
- 聚合函数 方法名称解析示例值说明自定义函数MaxMAX( a.`xx` )最大值是MinMIN( a.`xx` )最小值是CountCOUNT( a.`xx` )计数是SumSUM( a.`xx` )合计是AvgAVG( a.`xx` )平均是
- 数学函数 方法名称解析示例值说明自定义函数AbsABS( a.`xx` )绝对值是RoundROUND( a.`xx` ,2 )四舍五入是
- 字符串函数 方法名称解析示例值说明自定义函数StartsWithLIKE CONCAT( '%','xx' )左模糊否EndsWithLIKE CONCAT( xx','%' )右模糊否ContainsLIKE CONCAT( '%','xx','%' )全模糊否SubStringSUBSTRING( 'xxxxxx' ,1,3 )截取否ReplaceREPLACE( 'xxx','x','y' )替换否LenLEN( 'xxx' )长度是TrimTRIM( ' xx ' )修剪空格否TrimStartLTRIM( ' xx ' )修剪起始空格否TrimEndRTRIM( ' xx ' )修剪末尾空格否ToUpperUPPER( 'xx' )大写否ToLowerLOWER( 'xx' )小写否ConcatCONCAT(a.`xx1`,a.`xx2`)字符串拼接是
- 日期函数 方法名称解析示例值说明自定义函数DateDiffDATEDIFF( a.`xx`,b.`xx` )日期相差 返回相差天数是TimestampDiffTIMESTAMPDIFF( DAY,a.`xx`,b.`xx` )日期相差 指定时间单位是AddYearsDATE_ADD( a.`xx`,INTERVAL 1 YEAR )添加年份否AddMonthsDATE_ADD( a.`xx`,INTERVAL 1 MONTH )添加月份否AddDaysDATE_ADD( a.`xx`,INTERVAL 1 DAY )添加天数否AddHoursDATE_ADD( a.`xx`,INTERVAL 1 HOUR )添加时否AddMinutesDATE_ADD( a.`xx`,INTERVAL 1 MINUTE )添加分否AddSecondsDATE_ADD( a.`xx`,INTERVAL 1 SECOND )添加秒否AddMillisecondsDATE_ADD( a.`xx`,INTERVAL 1 MINUTE_SECOND )添加毫秒否YearYEAR( a.`xx` )获取年份是MonthMONTH( a.`xx` )获取月份是DayDAY( a.`xx` )获取天数是
- 查询函数 方法名称解析示例值说明自定义函数InIN ( a.`xx` ,'x1','x2','x3' )In查询是NotInNOT IN ( a.`xx` ,'x1','x2','x3' )Not In查询是
- 其它函数 方法名称解析示例值说明自定义函数NewGuidUUID()获取GUID否Equalsp.`ProductCode` = '123'比较否IfNullIFNULL( a.`xx`,0 )如果为空是CaseCASEcase是WhenWHENwhen是ThenTHENthen是ElseELSEelse是EndENDend是
- 类型转换 方法名称解析示例值说明自定义函数ToStringCONVERT( VARCHAR(255),123)转换 VARCHAR否ToDateTimeCONVERT( DATETIME,‘2022-09-16’)转换 DATETIME否ToDecimalCONVERT( DECIMAL(10,6),‘123’)转换 DECIMAL否ToDoubleCONVERT( NUMERIC(10,6),‘123’)转换 NUMERIC否ToSingleCONVERT( FLOAT,‘123’)转换 FLOAT否ToInt32CONVERT( INT,‘123’)转换 INT否ToInt64CONVERT( BIGINT,‘123’)转换 BIGINT否ToBooleanCONVERT( BIT,‘1’)转换 BIT否ToCharCONVERT( CHAR(2),'x')转换 CHAR否
- 聚合函数 方法名称解析示例值说明自定义函数MaxMAX( a.[xx] )最大值是MinMIN( a.[xx] )最小值是CountCOUNT( a.[xx] )计数是SumSUM( a.[xx] )合计是AvgAVG( a.[xx] )平均是
- 数学函数 方法名称解析示例值说明自定义函数AbsABS( a.[xx] )绝对值是RoundROUND( a.[xx] ,2 )四舍五入是
- 字符串函数 方法名称解析示例值说明自定义函数StartsWithLIKE ‘%’ 'xx'左模糊否EndsWithLIKE 'xx' ‘%’右模糊否ContainsLIKE ‘%’ 'xx' ‘%’全模糊否SubStringSUBSTRING( 'xxxxxx' ,1,3)截取否ReplaceREPLACE( 'xxx','x','y')替换否LenLEN( 'xxx' )长度是TrimStartLTRIM( ' xx ' )修剪起始空格否TrimEndRTRIM( ' xx ' )修剪末尾空格否ToUpperUPPER( 'xx' )大写否ToLowerLOWER( 'xx' )小写否OperationCreateTime >= @Now_1日期、数值、字符串范围比较是
- 日期函数 方法名称解析示例值说明自定义函数DateDiffDATEDIFF( DAY ,a.[xx],b.[xx])日期相差是AddYearsDATEADD( YEAR,a.[xx],1 )添加年份否AddMonthsDATEADD( MONTH,a.[xx],1 )添加月份否AddDaysDATEADD( DAY,a.[xx],1 )添加天数否AddHoursDATEADD( HOUR,a.[xx],1 )添加时否AddMinutesDATEADD( MINUTE,a.[xx],1 )添加分否AddSecondsDATEADD( SECOND,a.[xx],1 )添加秒否AddMillisecondsDATEADD( MILLISECOND,a.[xx],1 )添加毫秒否YearYEAR( a.[xx] )获取年份是MonthMONTH( a.[xx] )获取月份是DayDAY( a.[xx] )获取天数是
- 查询函数 方法名称解析示例值说明自定义函数InIN ( a.[xx] ,'x1','x2','x3')In查询是NotInNOT IN ( a.[xx] ,'x1','x2','x3')Not In查询是
- 其它函数 方法名称解析示例值说明自定义函数NewGuidNEWID()获取GUID否Equalsp.[ProductCode] = '123'比较否IsNullISNULL(a.[xx],0)是否为空是CaseCASEcase是WhenWHENwhen是ThenTHENthen是ElseELSEelse是EndENDend是
- SqlServer
- MySql
- Oracle
- PostgreSql
- Sqlite
添加自定义函数解析
代码语言:javascript复制 //注意:只能扩展未实现的方法名称 不能覆盖原有的实现
Models.DbType.MySQL.AddSqlFunc("方法名称", (visit, method, sqlStack) =>
{
//解析逻辑
});
九、数据库日志
代码语言:javascript复制 db.Aop.DbLog = (sql, dp) =>
{
Console.WriteLine($"执行Sql:{sql}");
if (dp != null)
{
foreach (var item in dp)
{
Console.WriteLine($"参数名称:{item.ParameterName} 参数值:{item.ParameterValue}");
}
}
};
十、事务
普通事务
代码语言:javascript复制 try
{
db.Ado.BeginTran();//开启事务
// 执行 CRUD
db.Ado.CommitTran();//提交事务
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
db.Ado.RollbackTran();//回滚事务
}
更大范围的事务
代码语言:javascript复制 try
{
db.BeginTran();//开启事务
// 执行 CRUD
db.CommitTran();//提交事务
}
catch (Exception ex)
{
db.RollbackTran();//回滚事务
Console.WriteLine(ex.Message);
}
十一、多租户
改变数据库
代码语言:javascript复制 //数据库配置可从Json配置文件加载
IDbContext db = new DbContext(new List<DbOptions>() {
new DbOptions()
{
DbId = "1",
DbType = Models.DbType.SQLServer,
ProviderName = "System.Data.SqlClient",
FactoryName = "System.Data.SqlClient.SqlClientFactory,System.Data",
ConnectionStrings = "server=localhost;database=Test;user=sa;pwd=123456789;min pool size=0;max pool size=100;connect timeout=120;"
},
new DbOptions()
{
DbId = "2",
DbType = Models.DbType.MySQL,
ProviderName = "MySqlConnector",
FactoryName = "MySqlConnector.MySqlConnectorFactory,MySqlConnector",
ConnectionStrings = "server=localhost;database=Test;user=root;pwd=123456789;port=3306;min pool size=0;max pool size=100;connect timeout=120;"
}});
db.ChangeDb("2");//切换到MySQL
十二、原生特性支持
代码语言:javascript复制 /// <summary>
/// 产品
/// </summary>
[Table("ProductMain")]
public class Product
{
/// <summary>
/// 产品ID
/// </summary>
[Key]
public int ProductId { get; set; }
/// <summary>
/// 产品编号
/// </summary>
[Column("ProductCode")]//不标记默认取当前属性名称
public string ProductCode { get; set; }
/// <summary>
/// 自定义1
/// </summary>
[NotMapped]
public string Custom1 { get; set; }
}
十三、原生Ado
代码语言:javascript复制 // 原始起步
// var conn = db.Ado.DbProviderFactory.CreateConnection();
// var cmd = conn.CreateCommand();
// 封装的方法分别以Execute和Create开头以及预处理 PrepareCommand 方法
// 该方法可以自动帮你处理执行的预操作,主要作用是代码复用。
// 当有非常复杂的查询 ORM不能满足需求的时候可以使用原生Ado满足业务需求
// 构建数据集核心扩展方法 分别有 FristBuild ListBuild DictionaryBuild DictionaryListBuild
var data = db.Ado.ExecuteReader(CommandType.Text, "select * from product", null).ListBuild<Product>();
十四、工作单元
注册数据库上下文和工作单元服务
代码语言:javascript复制var builder = WebApplication.CreateBuilder(args);
var configuration = builder.Configuration;
// 添加数据库上下文服务
builder.Services.AddFastDbContext();
// 添加工作单元服务
builder.Services.AddFastUnitOfWork();
// 加载数据库配置
builder.Services.Configure<List<DbOptions>>(configuration.GetSection("DbConfig"));
实际应用
代码语言:javascript复制 /// <summary>
/// 工作单元
/// </summary>
private readonly IUnitOfWork unitOfWork;
/// <summary>
/// 构造方法
/// </summary>
/// <param name="unitOfWork">工作单元</param>
public UnitOfWorkTestService(IUnitOfWork unitOfWork)
{
this.unitOfWork = unitOfWork;
}
/// <summary>
/// 测试
/// </summary>
/// <returns></returns>
public string Test()
{
//unitOfWork 对象无需显示使用using
var result1 = unitOfWork.Db.Insert(new Category()
{
CategoryName = "类别3"
}).Exceute();
var result2 = unitOfWork.Db.Insert(new Product()
{
ProductCode = "测试工作单元",
}).Exceute();
unitOfWork.Commit();
return "工作单元执行完成...";
}
十五、大数据导入
批复制 仅支持SqlServer Oracle MySql PostgreSql
代码语言:javascript复制 var list = new List<Product>();
for (int j = 1; j <= 100000; j )
{
list.Add(new Product()
{
CategoryId = 1,
ProductCode = $"测试编号_{Timestamp.CurrentTimestampSeconds()}_{j}",
ProductName = $"测试名称_{Timestamp.CurrentTimestampSeconds()}_{j}",
CreateTime = DateTime.Now,
Custom1 = $"测试自定义1_{Timestamp.CurrentTimestampSeconds()}_{j}",
Custom2 = $"测试自定义2_{Timestamp.CurrentTimestampSeconds()}_{j}",
Custom3 = $"测试自定义3_{Timestamp.CurrentTimestampSeconds()}_{j}",
Custom4 = $"测试自定义4_{Timestamp.CurrentTimestampSeconds()}_{j}",
Custom5 = $"测试自定义5_{Timestamp.CurrentTimestampSeconds()}_{j}",
Custom6 = $"测试自定义6_{Timestamp.CurrentTimestampSeconds()}_{j}",
Custom7 = $"测试自定义7_{Timestamp.CurrentTimestampSeconds()}_{j}",
Custom8 = $"测试自定义8_{Timestamp.CurrentTimestampSeconds()}_{j}",
Custom9 = $"测试自定义9_{Timestamp.CurrentTimestampSeconds()}_{j}",
Custom10 = $"测试自定义10_{Timestamp.CurrentTimestampSeconds()}_{j}",
Custom11 = $"测试自定义11_{Timestamp.CurrentTimestampSeconds()}_{j}",
Custom12 = $"测试自定义12_{Timestamp.CurrentTimestampSeconds()}_{j}",
});
}
db.Fast<Product>().BulkCopy(list);