今天学到了一个视角,叫做读者视角——从情商角度看就是换位思考。当我在写文章的时候,可能仅仅站在我的角度看待这个写的动作。那我就怎么写的爽怎么来,什么用词用字就按自己的习惯来书写,文章的深浅随心,反正我自己懂。而对于看到这篇文章的读者来说,就没有那么爽了,有的地方简单的过了头,有的地方又深涩难懂,浪费了半天的时间,并没有达到时间的收益。所以这篇文章就从浅入深逐步展开的方式阐述,希望看过的朋友给点建议哦~
1、什么是属性包(Property Bag)
这个名字来源无从考究了,我最早听说应该是在做VB组件或者Com组件的时候吧,感兴趣的朋友可以看看下面的vb代码,下面是来自亘古洪荒的讯息:
Set objPB = New PropertyBag
Call objPB.WriteProperty("PersistValue", obj, Nothing)
Set obj = Nothing
obj2 = objPB.ReadProperty("PersistValue", Nothing)
嗯嗯,看完能理解吗?对头,你猜的没错,它就是一个属性集合而已。 我下面使用c#定义一个类,你就能看出来其用法的精髓了。
public partial class CostCourse
{
/// <summary>
/// 费用科目ID
/// </summary>
public string CourseId { get; set; }
/// <summary>
/// 费用科目名称
/// </summary>
public string CourseName { get; set; }
// 属性包
public Dictionary<string, object> ExtendsObject = new Dictionary<string, object>();
}
是的,放在类里就是一个词典而已,因为是词典,也可以看作是上面CostCourse类的扩展。如果上面的类定义再增加一个索引属性,则使用起来更简单,不是吗?
public object this[string propertyName]
{
get { return this.ExtendsObject[propertyName]; }
set { this.ExtendsObject[propertyName] = value; }
}
2、EF Core为啥增加属性包特性
这就是开源社区的力量,社区内一直有人呼吁增加EF Core的动态支持,以便全方位的支持动态实体模型,呼声最高的有这三个特性:
-
阴影对象:这是关于在模型中定义某些实体或复杂类型,这些实体或复杂类型不会被实现为用户对象,而只是在DbContext实例中被跟踪为“状态”。这对于诸如多对多关联中的链接表之类的场景或任何其他情况下很有用,在这种情况下,整个实体都包含EF需要跟踪但用户选择不包含在对象模型中的信息。说了这么多,你看懂了吗?简言之,就是藏在后面只有EF core框架自己关注的东东字段,我们定义实体模型时不需要定义它了,使用时可以使用特别的方法获取。
-
属性包:因为之前的EF Core在实现代码时,就把EF模型和实体对象的映射关系写死了,因此很难再对其进行更改,以使EF能够实现更灵活的功能,所以提出了属性包概念。
-
适当的动态对象:具体是指支持实体和复杂类型,其中每个特定实例可以包含一组不同的属性。主要是对BLOB或JSON字段的支持,而不是将其分解为单独的标量属性。比如JSON对象的搜索,过滤等
上篇文章讲述了属性索引的使用,和这里的属性包有什么区别呢?
属性索引可以理解为对既有实体对象的扩展,我们姑且称之为 类的属性扩展;而属性包是对实体集合的扩展,我们姑且称之为类的扩展。简言之,属性包可以完成动态的增加一个新的实体类的映射。
3、实操一下
实操一下吧,实操前赞美下微软,微软出品,永远是那么的简单!Come On,Baby,三步搞定为我们的应用动态扩展一个实体类定义。
3.1 先构建表
不管你用什么方法,我相信你可以搞定一个表的定义和构建的。
CREATE TABLE `test2` (
`Id` int(11) NOT NULL AUTO_INCREMENT,
`Name` varchar(50) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,
`CreatedDate` datetime(0) NULL DEFAULT NULL,
`Desc` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,
PRIMARY KEY (`Id`) USING BTREE
)
3.2 在DbContext内增加动态注册的模型
一般是在 OnModelCreating重载方法内构建,闲言碎语莫要谈,今日就聊聊码代码。
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
//这里需要构建的模型名称、类型均可以先定义在配置数据源内,然后在初始化时,进行加载即可。
//因为是基于名称构建的,因此不存在硬编码问题。
modelBuilder.SharedTypeEntity<Dictionary<string, object>>("test2", c =>
{
c.IndexerProperty(typeof(int), "Id");
c.IndexerProperty(typeof(string), "Name").HasMaxLength(50).IsRequired();
c.IndexerProperty(typeof(DateTime), "CreatedDate");
c.IndexerProperty(typeof(string), "Desc").HasMaxLength(255);
});
OnModelCreatingPartial(modelBuilder);
}
3.3 使用模型
使用模型无非是增删改查,这里的操作很easy,也是大都基于字符串,因此很容易按照配置进行相应的修改。
//利用 context.Set<Dictionary<string, object>> 获取动态注册的模型
var test2s = context.Set<Dictionary<string, object>>("test2");
//增加一条记录
test2s.Add(new Dictionary<string, object>
{
["Name"] = "Beverages",
["CreatedDate"] = DateTime.Now,
["Desc"] = "Stuff to sip on"
});
//保存数据
context.SaveChanges();
//查询一条数据
var data = test2s.Single(x => x["Name"] == "Beverages");
//打印查到的数据
Console.WriteLine($"name={data["Name"]},desc = {data["Desc"]},createdData={data["CreatedDate"] }");
打印结果如下:
name=Beverages,desc = Stuff to sip on,createdData=2020-12-26 21:03:11
4、结语
又到了收尾的时候,通过EF Core 的属性包功能,好像撸一个PAAS平台没那么难了,期待大家伙今后的作品哦。
经过2020年疫情洗礼,国外的程序员好像都进行了闭关修炼,今年的产出也比往年更丰盛一些。特别是随着.NET 5的推出,沉寂很久的.NET市场有了几丝生气,在这里也祝愿.NET在2021年能够大放异彩,也不至于我老了老了,编程技能还要换成java(这才是重点)。