![c495043b4eb4ab72cf9e3e4f57804674.png](https://i-blog.csdnimg.cn/blog_migrate/2c24d33208788d6573d032a97f8adfee.jpeg)
LinqSharp 是个开源 LINQ 扩展库,它允许您编写简单代码来生成复杂查询,包括查询扩展和动态查询生成。
LinqSharp.EFCore 是对 EntityFramework 的增强库,提供更多数据注解、数据库函数及自定义储存规则等。
LinqSharp:为 LINQ 提供更多通用扩展github.com由于内容较多,将分篇介绍公开内容、原理及案例分享:
- LinqSharp:简化复杂查询
- LinqSharp:动态构建 LINQ 查询
- LinqSharp.EFCore:表设计数据注解
- LinqSharp.EFCore:字段标准化数据注解
- LinqSharp.EFCore:函数映射
- LinqSharp.EFCore:列式存储代理
- LinqSharp.EFCore:关联计算与审计
数据注解
LinqSharp 为 CodeFirst 模型提供了更多且易于使用的数据注解,分为:
- 表设计数据注解
- 数据标准化数据注解
表设计数据注解,是调用 Flunt API 的替代方案,方便编写 CodeFirst 模型。
表设计数据注解
表设计数据注解解析的内部实现是对 Flunt API 进行调用。
因此,生效功能实现,需要重写 DbContext 下的 OnModelCreating 方法:
public class ApplicationDbContext : DbContext
{
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
LinqSharpEF.OnModelCreating(this, base.OnModelCreating, modelBuilder);
}
}
索引(Index)
索引,是对数据库表中一列或多列值进行排序,以达到快速访问数据库表中的特定数据的能力。
Entity Framework 没有提供索引的数据注解,但在 Flunt API 提供了相应功能。
为了简化设计,LinqSharp 提供了 IndexAttribute 的数据注解实现。
假设,我们要创建这样的表:
- Id:主键
- Int0:非聚集索引
- Int1:唯一索引
- Int2_G1:和 Int3_G1 组成 唯一索引
- Int3_G1:和 Int2_G1 组成 唯一索引
![dffe2b5b7ddd7fb52f3f0486f873b3f1.png](https://i-blog.csdnimg.cn/blog_migrate/4ad1ea568fb60244ce21988ac11d6880.png)
在 CodeFirst 模型中使用 IndexAttribute:
public class LS_Index
{
[Key, DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public Guid Id { get; set; }
[Index(IndexType.Normal)]
public int Int0 { get; set; }
[Index(IndexType.Unique)]
public int Int1 { get; set; }
[Index(IndexType.Unique, Group = "Int2_G1&Int3_G1")]
public int Int2_G1 { get; set; }
[Index(IndexType.Unique, Group = "Int2_G1&Int3_G1")]
public int Int3_G1 { get; set; }
}
如果使用 MySQL,这段代码会生成如下索引:
![ffa3e2c2af369431785469f630adf252.png](https://i-blog.csdnimg.cn/blog_migrate/521984594336632ccd67f544a1ec3719.png)
自定义数据存储(Provider)
自定义数据存储是为复杂数据提供对象化地解析的功能,内部实现是对 Flunt API - HasConversion 的调用。
例如,设计一个 CodeFirst 模型,满足:
- 字段 NameModel 读取类型是 NameModel,存储为 JSON;
- 字段 Password 读取值是实际值,存储为 BASE64。
使用 ProviderAttribute 为指定字段进行定义:
public class LS_Provider
{
[Key]
public Guid Id { get; set; }
[StringLength(127)]
[Provider(typeof(PasswordProvider))]
public string Password { get; set; }
[StringLength(127)]
[Provider(typeof(JsonProvider<NameModel>))]
public NameModel NameModel { get; set; }
public class PasswordProvider : IProvider<string, string>
{
public override string ReadFromProvider(string value)
=> value.Flow(StringFlow.FromBase64);
public override string WriteToProvider(string model)
=> model.Flow(StringFlow.Base64);
}
}
JsonProvider 是 LinqSharp 的内建转换器,作用是储存 JSON 化。
自定义转换器类需要继承接口 IProvider,其中 TModel 为对象类型,TProvider 为储存类型。
IProvider 接口包含两个方法:
- “将数据写入储存介质”的转换方法:WriteToProvider(TModel model);
- “从储存介质读取数据”的转换方法:ReadFromProvider(TModel model);
例如,JsonProvider 的实现:
public class JsonProvider<TModel> : IProvider<TModel, string>
{
public override TModel ReadFromProvider(string value)
=> (TModel)JsonConvert.DeserializeObject(value, typeof(TModel));
public override string WriteToProvider(TModel model)
=> JsonConvert.SerializeObject(model);
}
使用 Provider,只需要将 Provider 绑定到属性字段即可。例如:
[Provider(typeof(JsonProvider<NameModel>))]
public NameModel NameModel { get; set; }
测试例子:
using (var context = ApplicationDbContext.UseMySql())
{
context.LS_Providers.Add(new LS_Provider
{
Password = "0416", // BASE64 储存
NameModel = new NameModel // JSON 储存
{
Name = "Jack",
NickName = "zmjack",
},
});
context.SaveChanges();
}
数据库记录:
![e48574ac3e093350cbd048ec8afc5c7c.png](https://i-blog.csdnimg.cn/blog_migrate/397acbc5f17b0965321525fc65409db4.png)