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、性能高、简单易用、表达式树智能解析 缺点:不具备有自动建库建表、数据迁移等复杂的功能 由于不同数据库差异较大 实现较为复杂 所以暂时不考虑实现
项目明细- Fast.Framework
- Fast.Framework.CustomAttribute
- Fast.Framework.Extensions
- Fast.Framework.Interfaces
- Fast.Framework.Logging
- Fast.Framework.Models
- 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>();