• 基于NET 6.0 自研轻量级ORM框架


    Fast Framework

    Author Mr-zhong

    Email 850856667@qq.com

    QQ群 693979005

    Open Source https://gitee.com/China-Mr-zhong/Fast.Framework

    前言

    为了实现快速开发,省去编写大量Sql时间,更好的面向对象编程由此诞生了 Fast Framework

    Fast Framework 是一个基于NET6.0 封装的轻量级 ORM 框架 支持数据库 SqlServer Oracle MySql PostgreSql Sqlite 由于底层使用System.Data.Common 抽象类封装 理论支持所有Ado.Net 实现的类库,差异部分可能需要额外处理。

    优点: 体积小、流畅API、性能高、简单易用、表达式树智能解析 缺点:不具备有自动建库建表、数据迁移等复杂的功能 由于不同数据库差异较大 实现较为复杂 所以暂时不考虑实现

    项目明细
    1. Fast.Framework
    2. Fast.Framework.CustomAttribute
    3. Fast.Framework.Extensions
    4. Fast.Framework.Interfaces
    5. Fast.Framework.Logging
    6. Fast.Framework.Models
    7. Fast.Framework.Utils
    快速入门

    手动创建

    var options = new DbOptions() //数据库选项
                    {
                        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;AllowLoadLocalInfile=True;"
                    };
    
                var ado = new Ado(options);//原生Ado
                var db = new DbContext(options);//数据库上下文
    

    依赖注入

    var builder = WebApplication.CreateBuilder(args);
    
    // 正式项目请用配置文件注入,为了测试方便直接引用实现类库
    builder.Services.AddScoped<IDbContext, DbContext>();
    
    //加载Json配置文件 使用Net自带容器只能注入List<DbOptions>
    builder.Services.Configure<List<DbOptions>>(configuration.GetSection("DbConfig"));
    
    
    特性支持

    原生支持微软封装好的特性,命名空间如下

    using System.ComponentModel.DataAnnotations.Schema;

    using System.ComponentModel.DataAnnotations;

    • 示例

      /// <summary>
          /// 产品模型
          /// </summary>
          [Table("Product")]
          public class ProductModel
          {
              [Key]
              public int ProductId { get; set; }
      
              /// <summary>
              /// 分类ID
              /// </summary>
              public int CategoryId { get; set; }
      
              /// <summary>
              /// 产品编号
              /// </summary>
              public string ProductCode { get; set; }
      
              /// <summary>
              /// 产品名称
              /// </summary>
              public string ProductName { get; set; }
      
              /// <summary>
              /// 创建日期
              /// </summary>
              public DateTime CreateDate { get; set; }
      
              /// <summary>
              /// 是否删除
              /// </summary>
              public bool IsDelete { get; set; }
      
          }
      
    插入

    实体对象插入

                    var product = new ProductModel()
                    {
                        CategoryId = 1,
                        ProductCode = "1001",
                        ProductName = "测试产品1",
                        CreateDate = DateTime.Now
                    };
    
                    var result = await db.Insert(product).ExecuteAsync();
    

    实体对象插入并返回自增ID 仅支持 SQLServer MySQL SQLite

                    var product = new ProductModel()
                    {
                        CategoryId = 1,
                        ProductCode = "1001",
                        ProductName = "测试产品1",
                        CreateDate = DateTime.Now
                    };
    
                    var result = await db.Insert(product).ExecuteReturnIdentityAsync();
    

    实体对象列表 批量插入

                    var list = new List<ProductModel>()
                    {
                        new ProductModel()
                        {
                            CategoryId=1,
                            ProductCode="1001",
                            ProductName="测试产品1",
                            CreateDate=DateTime.Now
                        },
                        new ProductModel()
                        {
                            CategoryId=1,
                            ProductCode="1002",
                            ProductName="测试产品2",
                            CreateDate=DateTime.Now,
                        }
                    };
    
                    var result = await db.Insert(list).ExecuteAsync();
    

    匿名对象插入 需要使用As方法显示指定表名称 如需返回自增ID 同上

                    var product = new
                    {
                        CategoryId = 1,
                        ProductCode = "1001",
                        ProductName = "测试产品1",
                        CreateDate = DateTime.Now
                    };
    
                    var result = await db.Insert(product).As("Product").ExecuteAsync();
    

    匿名对象列表批量插入

                    var list = new List<object>()
                    {
                        new
                        {
                            CategoryId=1,
                            ProductCode="1001",
                            ProductName="测试产品1",
                            CreateDate=DateTime.Now
                        },
                        new
                        {
                            CategoryId=1,
                            ProductCode="1002",
                            ProductName="测试产品2",
                            CreateDate=DateTime.Now,
                        }
                    };
    
                    var result = await db.Insert(list).As("Product").ExecuteAsync();
    

    字典插入 注意需要显示使用 <类型> 否则将无法重载到正确的方法

                    var data = new Dictionary<string, object>()
                    {
                        { "ProductCode","1001"},
                        { "ProdutName","测试产品1"},
                        { "CategoryId",1},
                        { "CreateDate",DateTime.Now}
                    };
    
                    var result = await db.Insert<ProductModel>(data).ExecuteAsync();
    
    删除

    实体对象无条件删除

    var result = await db.Delete<ProductModel>().ExecuteAsync();
    

    实体对象条件删除

    var result = await db.Delete<ProductModel>().Where(p => p.ProductId == 1).ExecuteAsync();
    

    无实体删除 无条件删除场景很有用,特别用法

    var result = await db.Delete<object>().As("Product").ExecuteAsync();
    
    更新

    实体对象更新 如果只是更新一条数据请务必带上Where条件

                    var product = new ProductModel()
                    {
                        ProductCode = "1001",
                        ProductName = "测试产品1"
                    };
    
                    var result = await db.Update(product).Where(p => p.ProductId == 1).ExecuteAsync();
    

    实体对象表达式更新 如果只是更新一条数据请务必带上Where条件

                    var result = await db.Update<ProductModel>(p => new ProductModel
                    {
                        ProductCode = "1001",
                        ProductName = p.ProductCode + p.ProductName
                    }).Where(p => p.ProductId == 1).ExecuteAsync();
    

    实体对象列表 批量更新 默认会查找标注主键属性作为更新条件 如果没有主键 需要显示使用Where 方法指定条件列名称

                    var list = new List<ProductModel>()
                    {
                        new ProductModel()
                        {
                            ProductId=1,
                            CategoryId=1,
                            ProductCode="1001",
                            ProductName="测试产品1",
                            CreateDate=DateTime.Now
                        },
                        new ProductModel()
                        {
                            ProductId=2,
                            CategoryId=1,
                            ProductCode="1002",
                            ProductName="测试产品2",
                            CreateDate=DateTime.Now,
                        }
                    };
    
                    var result = await db.Update(list).ExecuteAsync();
    

    匿名对象更新 需要使用As方法显示指定表名称 如果只是更新一条数据请务必带上Where条件

                    var product = new 
                    {
                        ProductCode = "1001",
                        ProductName = "测试产品1"
                    };
    
                    var result = await db.Update(product).As("product").Where(p => p.ProductId == 1).ExecuteAsync();
    

    字典更新 注意需要显示使用 <类型> 否则将无法重载到正确的方法

                    var data = new Dictionary<string, object>()
                    {
                        { "ProductCode","1001"},
                        { "ProdutName","测试产品1"},
                        { "CategoryId",1},
                        { "CreateDate",DateTime.Now}
                    };
    
                    var result = await db.Update<ProductModel>(data).Where(p => p.ProductId == 1).ExecuteAsync();
    
    查询

    单一对象

                    var data = await db.Query<ProductModel>().FirstAsync();
    

    列表

                    var data = await db.Query<ProductModel>().ToListAsync();
    

    分页

                    var pageData = await db.Query<ProductModel>().ToPageListAsync(1, 10);
    

    单个字典

                    var data = await db.Query<ProductModel>().DictionaryAsync();
    

    字典列表

                    var data = await db.Query<ProductModel>().DictionaryListAsync();
    

    查询并插入 同表复制数据或者跨表复制数据将非常有用

                    var result = await db.Query<ProductModel>().Where(p => p.ProductId == 1).Select(p => new
                    {
                        CategoryId = 2,
                        p.ProductCode,
                        p.ProductName
                    }).Insert<ProductModel>(p => new
                    {
                        p.CategoryId,
                        p.ProductCode,
                        p.ProductName
                    }).ExecuteAsync();// 需要调用ExecuteAsync 才会执行并返回受影响行数
    

    计数

                    var count = await db.Query<ProductModel>().CountAsync();
    

    任何

                    var count = await db.Query<ProductModel>().AnyAsync();
    

    条件

                    var data = await db.Query<ProductModel>().Where(p => p.IsDelete == true).ToListAsync();
    

    In 有好几个重载方法 不全部列出

                    var data = await db.Query<ProductModel>().In(p => p.ProductId, ids).ToListAsync();
    

    NotIn 有好几个重载方法 不全部列出

                    var data = await db.Query<ProductModel>().NotIn(p => p.ProductId, ids).ToListAsync();
    

    分组

                    var data = await db.Query<ProductModel>().GroupBy(p => new
                    {
                        p.ProductCode,
                        p.ProductName
                    }).ToListAsync();
    

    HavaVing 需要和GroupBy 组合

                    var data = await db.Query<ProductModel>().GroupBy(p => new
                    {
                        p.ProductCode,
                        p.ProductName
                    }).Having(p => SqlFunc.Count(1) > 1).ToListAsync();
    

    排序 默认ASC 升序

                    var data = await db.Query<ProductModel>().OrderBy(o => new { o.ProductId }, "DESC").ToListAsync();
    

    并集 多个查询合并成一个 列名个数和数据类型需要一一对应

                    var query1 = db.Query<ProductModel>().Select(s => new { s.ProductCode, s.ProductName });
    
                    var query2 = db.Query<ProductModel>().Select(s => new { s.ProductCode, s.ProductName });
    
                    var data = db.Union(query1, query2).ToListAsync();
    

    左连接

                    var data = db.Query<ProductModel>()
                        .LeftJoin<ProductCategoryModel>((p, c) => p.CategoryId == c.CategoryId)
                        .Select((p, c) => new
                        {
                            c.CategoryName,
                            p.ProductCode,
                            p.ProductName
                        }).ToListAsync();
    

    内连接

                    var data = db.Query<ProductModel>()
                        .InnerJoin<ProductCategoryModel>((p, c) => p.CategoryId == c.CategoryId)
                        .Select((p, c) => new
                        {
                            c.CategoryName,
                            p.ProductCode,
                            p.ProductName
                        }).ToListAsync();
    

    选择 返回指定字段

                    var data = db.Query<ProductModel>().Select(p =>
                    new
                    {
                        p.ProductCode,
                        p.ProductName
                    }).ToListAsync();
    

    模糊查询 StartsWith 左模糊 EndsWith 右模糊 Contains 全模糊

                    var data = db.Query<ProductModel>().Where(p => p.ProductName.Contains("测试")).ToListAsync();
    

    动态条件表达式

                    var ex = DynamicWhereExpression.Create<ProductModel>();
    
                    // 两个子表达式参数名 p 必须一致
                    ex.AndIF(1 == 1, p => p.ProductCode == "1001");
                    ex.AndIF(1 == 1, p => p.ProductName == "测试");
    
                    var data = db.Query<ProductModel>().Where(ex.Build()).ToListAsync();
    
    函数类

    Fast.Framework.SqlFunc.cs

    Fast.Framework.Extensions.SqlFuncExtensionscs.cs

    对比两种使用方式 两种方式是等价的 我更喜欢使用扩展方法

                    var data = db.Query<ProductModel>().Select(s => new
                    {
                        Case1 = 1.Count(),
                        Case2 = SqlFunc.Count(1)
                    }).ToListAsync();
    

    特殊方法Call 如果您需要在表达式new一个对象调用方法或者获取属性值 需要显示调用这个方法 因为表达式默认解析类型是SqlString

                    var data = db.Query<ProductModel>().Where(p => p.ProductCode == new { ProductCode = "123" }.Call().ProductCode).ToListAsync();
    
    输出Sql
    • 使用Tostring() Insert Delete Update Query 对象都支持
                    var sql = db.Query<ProductModel>().ToString();
                    Console.WriteLine(sql);
    
    • 使用数据库日志委托
                    db.Aop.DbLog = (sql, parameters) =>
                      {
                          Console.WriteLine($"ExecuteSql:{sql}");
                          if (parameters != null)
                          {
                              foreach (var item in parameters)
                              {
                                  Console.WriteLine($"参数名:{item.ParameterName} 参数值:{item.Value}");
                              }
                          }
                          Console.WriteLine($"ExecuteTime:{DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss.fff")}");
                          Console.WriteLine();
                      };
    
    Ado 原生

    如果DbContext 无法满足复杂查询需求 可以使用Ado原生满足各种复杂查询

                    // 这是一个简单的示例 仅供参考
    				var sql = "select * from product where productcode=@ProductCode;select 100;";
    
                    var paramters = new Dictionary<string, object>()
                    {
                        { "ProductCode","1001"}
                    };
    
                    var reader = db.Ado.ExecuteReaderAsync(sql, db.Ado.SqlParametersBuild(paramters));
    
                    var data = await reader.ListBuildAsync<ProductModel>();
    
                    var count = await reader.FristBuildAsync<int>();
    
  • 相关阅读:
    Nginx网络服务之监控模块
    项目实战:抽取中央控制器 DispatcherServlet
    Go语言学习笔记——日期时间处理库Carbon
    散射介质成像中弹道光子、蛇形光子、散射光子的概念
    源码分析:设备创建链接和断开链接
    基于Leaflet 和 PostGIS 的服务端 Web GIS 应用程序开发教程
    如何在 Linux 服务器上配置基于 SSH 密钥的身份验证
    数云融合 | 旧叔讲文旅:数字化进程中功不可没的二维码
    【兔子机器人】项目资料汇总及任务流程
    【计算机网络】 静态库与动态库
  • 原文地址:https://www.cnblogs.com/China-Mr-zhong/p/15992962.html