当前位置 : 主页 > 编程语言 > 其它开发 >

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

来源:互联网 收集:自由互联 发布时间:2022-05-17
Fast Framework Author Mr-zhong Email 850856667@qq.com QQ群 693979005 Open Source https://gitee.com/China-Mr-zhong/Fast.Framework 前言 为了实现快速开发,省去编写大量Sql时间,更好的面向对象编程由此诞生了 Fas
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>();
上一篇:图解机器学习 | 降维算法详解
下一篇:没有了
网友评论