ToB企服应用市场:ToB评测及商务社交产业平台

标题: Fast.Framework ORM 于中秋节后 正式开源 [打印本页]

作者: 美丽的神话    时间: 2022-9-17 08:39
标题: Fast.Framework ORM 于中秋节后 正式开源
Fast Framework

作者 Mr-zhong
开源项目地址 https://github.com/China-Mr-zhong/Fast.Framework
QQ交流群 954866406 欢迎小伙伴加入交流探讨技术
一、前言

Fast Framework 是一个基于NET6.0 封装的轻量级 ORM 框架 支持多种数据库 SqlServer Oracle MySql PostgreSql Sqlite
优点: 体积小、可动态切换不同实现类库、原生支持微软特性、流畅API、使用简单、性能高、模型数据绑定采用 委托+缓存、强大的表达式解析、子查询的原生支持、复杂表达式含成员变量解析,解析性能是目前常见框架中 No1 主要是有缓存的支持 、源代码可读性强。
缺点:目前仅支持Db Frist Code Frist 暂时不考虑 主要是需要花费大量时间和精力。
二、项目明细

名称说明Fast.Framework接口实现类库(框架核心接口实现)Fast.Framework.AopAop类库(基于微软DispatchProxy抽象类封装)Fast.Framework.Extensions扩展类库(主要扩展框架核心方法,方便使用)Fast.Framework.Interfaces接口类库(框架核心接口定义)Fast.Framework.Logging日志类库(主要实现自定义文件日志)Fast.Framework.Models模型 框架所用到的实体类Fast.Framework.Utils工具类库Fast.Framework.Test控制台终端测试项目Fast.Framework.UnitTest单元测试项目Fast.Framework.Web.TestWeb测试项目三、核心对象

  1. IAdo ado = new AdoProvider(new DbOptions()
  2. {
  3. DbId = "1",
  4. DbType = DbType.MySQL,
  5. ProviderName = "MySqlConnector",
  6. FactoryName = "MySqlConnector.MySqlConnectorFactory,MySqlConnector",
  7. ConnectionStrings = "server=localhost;database=Test;user=root;pwd=123456789;port=3306;min pool size=3;max pool size=100;connect timeout=30;"
  8. });
复制代码
  1. IDbContext db = new DbContext(new List<DbOptions>() {
  2. new DbOptions()
  3. {
  4. DbId = "1",
  5. DbType = DbType.MySQL,
  6. ProviderName = "MySqlConnector",
  7. FactoryName = "MySqlConnector.MySqlConnectorFactory,MySqlConnector",
  8. ConnectionStrings = "server=localhost;database=Test;user=root;pwd=123456789;port=3306;min pool size=3;max pool size=100;connect timeout=30;"
  9. }});
复制代码
依赖注入
  1. // 注册服务
  2. builder.Services.AddScoped<IDbContext, DbContext>();
  3. // 数据库选项支持Options接口注入 不是很理解的可以看代码实现
  4. builder.Services.Configure<List<DbOptions>>(configuration.GetSection("DbConfig"));
  5. // 产品服务类 通过构造方法注入
  6. public class ProductService
  7. {
  8. /// <summary>
  9. /// 数据库
  10. /// </summary>
  11. private readonly IDbContext db;
  12. /// <summary>
  13. /// 构造方法
  14. /// </summary>
  15. /// <param name="db">数据库</param>
  16. public ProductService(IDbContext db)
  17. {
  18. this.db = db;
  19. }
  20. }
复制代码
四、插入

  1. var product = new Product()
  2. {
  3. ProductCode = "1001",
  4. ProductName = "测试商品1"
  5. };
  6. var result = await db.Insert(product).ExceuteAsync();
  7. Console.WriteLine($"实体对象插入 受影响行数 {result}");
复制代码
  1. var product = new Product()
  2. {
  3. ProductCode = "1001",
  4. ProductName = "测试产品1"
  5. };
  6. var result = await db.Insert(product).ExceuteReturnIdentityAsync();
  7. Console.WriteLine($"实体对象插入 返回自增ID {result}");
复制代码
  1. var list = new List<Product>();
  2. for (int i = 0; i < 2100; i++)
  3. {
  4. list.Add(new Product()
  5. {
  6. ProductCode = $"编号{i + 1}",
  7. ProductName = $"名称{i + 1}"
  8. });
  9. }
  10. var result = await db.Insert(list).ExceuteAsync();
  11. Console.WriteLine($"实体对象列表插入 受影响行数 {result}");
复制代码
  1. var obj = new
  2. {
  3. ProductCode = "1001",
  4. ProductName = "测试商品1"
  5. };
  6. //注意:需要使用As方法显示指定表名称
  7. var result = await db.Insert(obj).As("product").ExceuteAsync();
  8. Console.WriteLine($"匿名对象插入 受影响行数 {result}");
复制代码
  1. var list = new List<object>();
  2. for (int i = 0; i < 2100; i++)
  3. {
  4. list.Add(new
  5. {
  6. ProductCode = $"编号{i + 1}",
  7. ProductName = $"名称{i + 1}"
  8. });
  9. }
  10. //注意:需要使用As方法显示指定表名称
  11. var result = await db.Insert(list).As("Product").ExceuteAsync();
  12. Console.WriteLine($"匿名对象列表插入 受影响行数 {result}");
复制代码
  1. var product = new Dictionary<string, object>()
  2. {
  3. {"ProductCode","1001"},
  4. { "ProductName","测试商品1"}
  5. };
  6. //注意:需要显示指定类型否则无法重载到正确的方法,如果没有实体类型可用object类型并配合As方法显示指定表名称.
  7. var result = await db.Insert<Product>(product).ExceuteAsync();
  8. Console.WriteLine($"字典插入 受影响行数 {result}");
复制代码
  1. var list = new List<Dictionary<string, object>>();
  2. for (int i = 0; i < 2100; i++)
  3. {
  4. list.Add(new Dictionary<string, object>()
  5. {
  6. {"ProductCode","1001"},
  7. { "ProductName","测试商品1"}
  8. });
  9. }
  10. //注意:需要显示指定泛型类型否则无法重载到正确的方法,如果没有实体可用object类型并配合As方法显示指定表名称.
  11. var result = await db.Insert<Product>(list).ExceuteAsync();
  12. Console.WriteLine($"字典列表插入 受影响行数 {result}");
复制代码
五、删除

  1. var product = new Product()
  2. {
  3. ProductId = 1,
  4. ProductCode = "1001",
  5. ProductName = "测试商品1"
  6. };
  7. //注意:必须标记KeyAuttribute特性 否则将抛出异常
  8. var result = await db.Delete(product).ExceuteAsync();
  9. Console.WriteLine($"实体删除 受影响行数 {result}");
复制代码
  1. var result = await db.Delete<Product>().ExceuteAsync();
  2. Console.WriteLine($"无条件删除 受影响行数 {result}");
复制代码
  1. var result = await db.Delete<Product>().Where(w => w.ProductId == 1).ExceuteAsync();
  2. Console.WriteLine($"条件删除 受影响行数 {result}");
复制代码
  1. //特殊用法 如需单个条件或多个可搭配 WhereColumn或WhereColumns方法
  2. var result = await db.Delete<object>().As("Product").ExceuteAsync();
  3. Console.WriteLine($"无实体删除 受影响行数 {result}");
复制代码
六、更新

  1. var product = new Product()
  2. {
  3. ProductId = 1,
  4. ProductCode = "1001",
  5. ProductName = "测试商品1"
  6. };
  7. //注意:标记KeyAuttribute特性属性或使用Where条件,为了安全起见全表更新将必须使用Where方法
  8. var result = await db.Update(product).ExceuteAsync();
  9. Console.WriteLine($"对象更新 受影响行数 {result}");
复制代码
  1. var result = await db.Update<Product>(new Product() { ProductCode = "1001", ProductName = "1002" })
  2. .Columns("ProductCode", "ProductName").ExceuteAsync();
  3. // 字段很多的话可以直接new List<string>(){"列1","列2"}
复制代码
  1. var result = await db.Update<Product>(new Product() { ProductCode = "1001", ProductName = "1002" })
  2. .IgnoreColumns("Custom1").ExceuteAsync();
  3. // 同上使用方法一样
复制代码
  1. var list = new List<Product>();
  2. for (int i = 0; i < 2022; i++)
  3. {
  4. list.Add(new Product()
  5. {
  6. ProductCode = $"编号{i + 1}",
  7. ProductName = $"名称{i + 1}"
  8. });
  9. }
  10. //注意:标记KeyAuttribute特性属性或使用WhereColumns方法指定更新条件列
  11. var result = await db.Update(list).ExceuteAsync();
  12. Console.WriteLine($"对象列表更新 受影响行数 {result}");
复制代码
  1. var obj = new
  2. {
  3. ProductId = 1,
  4. ProductCode = "1001",
  5. ProductName = "测试商品1"
  6. };
  7. //注意:需要显示指定表名称 以及更新条件 使用 Where或者WhereColumns方法均可
  8. var result = await db.Update(obj).As("product").WhereColumns("ProductId").ExceuteAsync();
  9. Console.WriteLine($"匿名对象更新 受影响行数 {result}");
复制代码
  1. var list = new List<object>();
  2. for (int i = 0; i < 2022; i++)
  3. {
  4. list.Add(new
  5. {
  6. ProductId = i + 1,
  7. ProductCode = $"编号{i + 1}",
  8. ProductName = $"名称{i + 1}"
  9. });
  10. }
  11. //由于是匿名对象需要显示指定表名称,使用WhereColumns方法指定更新条件列
  12. var result = await db.Update(list).As("Product").WhereColumns("ProductId").ExceuteAsync();
  13. Console.WriteLine($"匿名对象列表更新 受影响行数 {result}");
复制代码
  1. var product = new Dictionary<string, object>()
  2. {
  3. { "ProductId",1},
  4. {"ProductCode","1001"},
  5. { "ProductName","测试商品1"}
  6. };
  7. //注意:需要显示指定泛型类型否则无法重载到正确的方法并且使用WhereColumns方法指定条件列
  8. var result = await db.Update<Product>(product).WhereColumns("ProductId").ExceuteAsync();
  9. Console.WriteLine($"字典更新 受影响行数 {result}");
复制代码
  1. var list = new List<Dictionary<string, object>>();
  2. for (int i = 0; i < 2022; i++)
  3. {
  4. list.Add(new Dictionary<string, object>()
  5. {
  6. { "ProductId",i+1},
  7. {"ProductCode",$"更新编号:{i+1}"},
  8. { "ProductName",$"更新商品:{i + 1}"}
  9. });
  10. }
  11. //注意:需要显示指定泛型类型否则无法重载到正确的方法并且使用WhereColumns方法执行条件列
  12. var result = await db.Update<Product>(list).WhereColumns("ProductId").ExceuteAsync();
  13. Console.WriteLine($"字典列表更新 受影响行数 {result}");
复制代码
  1. var product = new Product()
  2. {
  3. ProductId = 1,
  4. ProductCode = "1001",
  5. ProductName = "测试商品1"
  6. };
  7. var result = await db.Update(product).Where(p => p.ProductId == 100).ExceuteAsync();
  8. Console.WriteLine($"表达式更新 受影响行数 {result}");
复制代码
七、查询

  1. var data = await db.Query<Product>().FristAsync();
复制代码
  1. var data = await db.Query<Product>().ToListAsync();
复制代码
  1. var data = await db.Query<Product>().ToDictionaryAsync();
复制代码
  1. var data = await db.Query<Product>().ToDictionaryListAsync();
复制代码
  1. var page = new Pagination() { Page = 1, PageSize = 100 };
  2. var data = await db.Query<Product>().ToPageListAsync(page);
复制代码
  1. var data = await db.Query<Product>().CountAsync();
复制代码
  1. var data = await db.Query<Product>().AnyAsync();
复制代码
  1. var data = await db.Query<Product>().Where(w => w.ProductId == 1);
  2. //需要调用返回数据结果的方法 例如:ToListAsync
复制代码
  1. var data = await db.Query<Product>().Where(w => w.ProductName.StartsWith("左模糊") || w.ProductName.EndsWith("右模糊") || w.ProductName.Contains("全模糊"));
复制代码
  1. var data = await db.Query<Product>().Where(w => !w.ProductName.StartsWith("左模糊") || !w.ProductName.EndsWith("右模糊") || !w.ProductName.Contains("全模糊"));
  2. //由于没有专门去扩展 Not Like 方法,可以用取反或使用比较变通实现 例如 w.ProductName.StartsWith("左模糊")==false
  3. //Mysql举例 最终解析后的结果为 `ProductName` Like '%左模糊' = 0 这种用法数据库是支持的 相当于 Not Like
复制代码
  1. var data = await db.Query<Product>().Select(s => new
  2. {
  3. s.ProductId,
  4. s.ProductName
  5. }).ToListAsync();
复制代码
  1. var data = await db.Query<Product>().GroupBy(s => new
  2. {
  3. s.ProductId,
  4. s.ProductName
  5. }).ToListAsync();
复制代码
  1. var sql = db.Query<Order>().InnerJoin<OrderDetail>((a, b) => a.OrderId == b.OrderId).GroupBy((a, b) => new
  2. {
  3. a.OrderCode
  4. }).Select((a, b) => new
  5. {
  6. a.OrderCode,
  7. Sum_Qty = SqlFunc.Sum(b.Qty)//支持嵌套
  8. }).ToListAsync();
复制代码
  1. var data = await db.Query<Product>().OrderBy(s => new
  2. {
  3. s.CreateTime
  4. }).ToListAsync();
  5. //这是多个字段排序使用方法 还有其它重载方法
复制代码
  1. var data = await db.Query<Product>().GroupBy(s => new
  2. {
  3. s.ProductId,
  4. s.ProductName
  5. }).Having(s => SqlFunc.Count(s.ProductId) > 1).ToListAsync();
  6. //必须先使用GroupBy方法 懂得都懂
复制代码
  1. var data = await db.Query<Product>().
  2. LeftJoin<Class1>((a, b) => a.ProductId == b.ProductId).ToListAsync();
  3. // 右连接对应的是 RightJoin 内连接对应 InnerJoin
复制代码
  1. var query1 = db.Query<Product>();
  2. var query2 = db.Query<Product>();
  3. db.Union(query1, query2);//联合
  4. db.UnionAll(query1, query2);//全联合
  5. //执行查询调用Toxx方法
复制代码
  1. //方式1
  2. var result1 = await db.Query<Product>().Where(w => w.ProductId == 1489087).Select(s => new
  3. {
  4. s.ProductCode,
  5. s.ProductName
  6. }).Insert<Product>(p => new
  7. {
  8. p.ProductCode,
  9. p.ProductName
  10. });
  11. //方式2 需要注意的是 显示指定不带 列标识符 例如 `列名称1` 如有字段冲突 可自行加上标识符
  12. var result2 = await db.Query<Product>().Where(w => w.ProductId == 1489087).Select(s => new
  13. {
  14. s.ProductCode,
  15. s.ProductName
  16. }).Insert("表名称 同实例不同库 可以使用 db.数据库名称.表名称 ", "列名称1", "列名称2", "`带标识的列名称3`");
  17. //方式3 需要注意同方式2 一样
  18. var result3 = await db.Query<Product>().Where(w => w.ProductId == 1489087).Select(s => new
  19. {
  20. s.ProductCode,
  21. s.ProductName
  22. }).Insert("表名称 同实例不同库 可以使用 db.数据库名称.表名称 ", new List<string>() { "列名称1" });
复制代码
  1. // 方式1
  2. var data1 = await db.Query<Product>().Where(w => SqlFunc.In(w.ProductCode, "1001", "1002")).ToListAsync();
  3. // 方式2
  4. var data2 = await db.Query<Product>().Where(w => SqlFunc.In(w.ProductCode, new List<string>() { "123", "456" })).ToListAsync();
  5. // 方式3 需要动态更新IN值 使用这种
  6. var list = new List<string>() { "123", "456" };
  7. var data3 = await db.Query<Product>().Where(w => SqlFunc.In(w.ProductCode, list)).ToListAsync();
  8. // 方法4 参数同上一样 单独分离IN和NotIN 是为了兼容匿名查询
  9. var data4 = await db.Query<Product>().In("字段名称", "1001", "1002").ToListAsync();
复制代码
  1. var subQuery = db.Query<Product>().Where(w => w.ProductId == 1).Select(s => s.ProductName);
  2. var sql1 = db.Query<Product>().Select(s => new Product()
  3. {
  4. Custom1 = db.SubQuery<string>(subQuery)// SubQuery 的泛型是根据你左边赋值的属性类型来定义
  5. }).ToListAsync();
  6. // 这种没有使用new 的 泛型可随意定义 实际作用就是避免 对象属性赋值类型冲突的问题
  7. var sql2 = db.Query<Product>().Select(s => db.SubQuery<string>(subQuery)).ToListAsync();
复制代码
八、Lambda表达式

  1. var list = new List<string>() { "1001" };
  2. Expression<Func<Product, bool>> ex = p => SqlFunc.In(p.ProductCode, list);
  3. for (int i = 1; i <= 3; i++)
  4. {
  5. list.Add($"动态添加参数{i}");
  6. var stopwatch1 = new Stopwatch();
  7. stopwatch1.Start();
  8. var result = ex.ResolveSql(new ResolveSqlOptions()
  9. {
  10. DbType = Models.DbType.MySQL,
  11. ResolveSqlType = ResolveSqlType.Where
  12. });
  13. stopwatch1.Stop();
  14. Console.WriteLine($"解析耗时:{stopwatch1.ElapsedMilliseconds}ms {stopwatch1.ElapsedMilliseconds / 1000.00}s 解析Sql字符串:{result.SqlString}");
  15. }
复制代码
九、数据库日志
  1. 解析耗时:14ms 0.014s 解析Sql字符串:p.`ProductCode` IN ( @2dac7a1c4aa64036aeee858b86fbd3a4_0,@2dac7a1c4aa64036aeee858b86fbd3a4_1 )
  2. 解析耗时:0ms 0s 解析Sql字符串:p.`ProductCode` IN ( @3b6b8fcb2f674cf490d44f97525c3c2b_0,@3b6b8fcb2f674cf490d44f97525c3c2b_1,@3b6b8fcb2f674cf490d44f97525c3c2b_2 )
  3. 解析耗时:0ms 0s 解析Sql字符串:p.`ProductCode` IN ( @4447c5d65e8a49c9b04549b7aac868b2_0,@4447c5d65e8a49c9b04549b7aac868b2_1,@4447c5d65e8a49c9b04549b7aac868b2_2,@4447c5d65e8a49c9b04549b7aac868b2_3 )
复制代码
十、事务

  1. var ex = DynamicWhereExp.Create<Product>().AndIF(1 == 1, a => a.DeleteMark == true).Build();
  2. var data =await db.Query<Product>().Where(ex).ToListAsync();
复制代码
  1. db.Aop.DbLog = (sql, dp) =>
  2. {
  3. Console.WriteLine($"执行Sql:{sql}");
  4. if (dp != null)
  5. {
  6. foreach (var item in dp)
  7. {
  8. Console.WriteLine($"参数名称:{item.ParameterName} 参数值:{item.Value}");
  9. }
  10. }
  11. };
复制代码
十一、多租户

  1. try
  2. {
  3. await db.Ado.BeginTranAsync();//开启事务
  4. // 执行 CRUD
  5. await db.Ado.CommitTranAsync();//提交事务
  6. }
  7. catch (Exception ex)
  8. {
  9. Console.WriteLine(ex.Message);
  10. await db.Ado.RollbackTranAsync();//回滚事务
  11. }
复制代码
十二、原生特性支持
  1. using (var tran = new TransactionScope(TransactionScopeAsyncFlowOption.Enabled))
  2. {
  3. // 执行你的增删改查
  4. // 可使用原生Ado或DbContext对象的CURD方法
  5. tran.Complete();//提交事务
  6. }
复制代码
十三、原生Ado使用
  1. //数据库配置可从Json配置文件加载
  2. IDbContext db = new DbContext(new List<DbOptions>() {
  3. new DbOptions()
  4. {
  5. DbId = "0",
  6. DbType = Models.DbType.SQLServer,
  7. ProviderName = "System.Data.SqlClient",
  8. FactoryName = "System.Data.SqlClient.SqlClientFactory,System.Data",
  9. ConnectionStrings = "server=localhost;database=Test;user=sa;pwd=123456789;min pool size=3;max pool size=100;connect timeout=30;"
  10. },
  11. new DbOptions()
  12. {
  13. DbId = "1",
  14. DbType = Models.DbType.MySQL,
  15. ProviderName = "MySqlConnector",
  16. FactoryName = "MySqlConnector.MySqlConnectorFactory,MySqlConnector",
  17. ConnectionStrings = "server=localhost;database=Test;user=root;pwd=123456789;port=3306;min pool size=3;max pool size=100;connect timeout=30;"
  18. }});
  19. db.ChangeDb("1");//切换到MySQL
复制代码
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!




欢迎光临 ToB企服应用市场:ToB评测及商务社交产业平台 (https://dis.qidao123.com/) Powered by Discuz! X3.4