前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >一个可用于生产项目 基于 .NET 6 自研ORM

一个可用于生产项目 基于 .NET 6 自研ORM

作者头像
郑子铭
发布2023-08-29 10:18:37
2460
发布2023-08-29 10:18:37
举报
文章被收录于专栏:DotNet NB && CloudNative
一、前言

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);
本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2023-05-06,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 DotNet NB 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 一、前言
  • 二、项目明细
  • 三、核心对象
  • 四、插入
  • 五、删除
  • 六、更新
  • 七、查询
  • 八、Lambda表达式
  • 九、数据库日志
  • 十、事务
  • 十一、多租户
  • 十二、原生特性支持
  • 十三、原生Ado
  • 十四、工作单元
  • 十五、大数据导入
相关产品与服务
数据库
云数据库为企业提供了完善的关系型数据库、非关系型数据库、分析型数据库和数据库生态工具。您可以通过产品选择和组合搭建,轻松实现高可靠、高可用性、高性能等数据库需求。云数据库服务也可大幅减少您的运维工作量,更专注于业务发展,让企业一站式享受数据上云及分布式架构的技术红利!
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档