【ASP.NET Core】EF Core - “影子属性”
有朋友说老周近来博客更新较慢,确实有些慢,因为有些 bug 要研究,另外就是老周把部分内容转到直播上面,所以写博客的内容减少了一点。
老周觉得,视频直播可能会好一些,虽然我的水平一般,不过直播时,老周可以现场演示,可能会比看博客效果要好(因为现场演示,有时候会有失误,没办法,水平有限)。还有一个,就是.NET 的资料其实很多,毕竟也发展了十几年了,有些东西如果别人都写过了,那我也不好意思重复了。.NET Core 尽管是跨平台版本,但核心依然是.net 基础,我们不需要全新去学习,只要掌握一些新的变化就可以了。目前比较期待 .NET Core 3 的正式发布,等正式上线了,老周再挑一些有意义的内容写一下。
此外,老周也可能会写一写其他方面的博客,比如 Python、GO、Ruby、Typescript 等。老周并不是只会玩.NET ,只不过老周是主攻 .NET,在接触 .NET 之前,老周就学过很多东西,比如古老的 QBasic、Pascal ,老周在上初中时就学过。后来向 VB、C、C++ 进攻,顺便把 Ruby、Python、PB 也调戏一下,后来有一段时间,Delphi 和 E 语言也挺流行的,所以顺便也玩了两把。
再后来,学过 Java 和 PHP,抛 Java 而投 .NET 是因为 Java 太复杂,效率不高,没有深度把玩的兴趣。现在所谓的 Python 很热门纯属是商业炒作,Python 又不是什么新玩意儿,很古老了,当然相对于 C 来说,是新了一点,究其特点,就是一种脚本语言(虽然有人死要说它不是脚本语言)。现在网上更有些无知小辈,以为自己会写几行 Python 代码就到处去蹭热点,告诉你,老周当年学各种编程语言时,说不定你还没出生呢。所以,如果你真心喜欢 Python 的话,你用心去学就是了(其实老周也喜欢用 Python 来做图表),不必理会商业炒作。
记得去年 C 语言也被商业炒作了几个月,再往前几年,Javascript 和 Web 前端也被拼命炒作,说得好像 js 是万能的似的,吓得老周都不敢写前端了。最近几年,IT 界开始怀旧了,各种远古生物都被挖出来了,可能是现在计算机行业已经没什么可以创新的原因吧。现在说得较多的是人工智障,这个可以用,也可以不用,反正不痛不痒,算不上生产力革命(至少其震动效果比不上当年 Office 问世时对企业生产的影响大)。不过,人工智障在某些辅助领域还是有用的,比如现在有些小区的智能门,应用效果还可以。但是,漏洞也是百出的,总之,人类可以用它来进行辅助,但不能过于依赖它。它不能解决所有问题。
许多科幻小说都会说人类会被机器人消灭。机器人也是人创造出来的,机器不可能比人强,也不可能灭掉人类(除非机器人比奥特曼里面的超兽还牛逼)。如果人类真的智力在衰减,那么根源还是在人类自己。说白了就是,只有可能是人类自己灭掉自己。你也不用觉得太恐怖,其实只要你不要太依赖机器就好,不要失去你的本能和思考方式就行。
就像我们码农,老周也一样,天天跟计算机打交道,但老周一直坚持:用电脑,但不依赖电脑,多做些机器不能做的事。再加一句:科学只能解决数学和工程问题,而人的问题,需要哲学和美学来解决。
=============================================================================
好了,以上的都是 F 话,下面咱们聊正题。今天咱们耍一下 EF Core 中的影子属性。这个词翻译版本 TMD 多,有翻译为“卷影属性”的,现在的文档又改为“阴影属性”,这不好听,太有心理阴影了,故而,老周觉得,叫“影子属性”好一些。
不管叫什么,你只要知道它是个啥就行。老周喜欢一句话总结,所以,来一句话:
模型类中没有定义的,但数据表中存在的属性——即模型类与数据表中没有对应关系的属性。
老周就用一个简单的示例来说明一下吧。这个示例也是老周在视频直播时用的。
假设,有个模型类,叫 Student。
public class Student
{
public int Id { get; set; }
public string Name { get; set; }
public int Age { get; set; }
}
但我想要一个属性,用来记录数据记录被写进数据库的时间,即还有一个属性,叫 InsertTime,不过,这个属性在 Student 类中是没有定义的,但在数据表中是有这一字段的。
因此,在从 DbContext 类派生时,需要重写 OnModelCreating 方法,通过 Model Builder 来定义这个“隐藏”的属性。
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.Entity<Student>().Property<DateTime>("InsertTime");
}
这个 InsertTime 属性就成了影子属性了。
下面是 DbContext 派生类的完整代码,我放出来是方便你去抄袭的,放心吧,无版权税的,尽管抄。
public class MyContext : DbContext
{
public DbSet<Student> Students { get; set; } protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
optionsBuilder.UseSqlServer(@"server=(localdb)\MSSQLLocalDB;database=TestDb");
} protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.Entity<Student>().Property<DateTime>("InsertTime");
}
}
现在,到 Startup 类中,注册一下服务,让自定义的数据库上下文可以进行依赖注入。
public void ConfigureServices(IServiceCollection services)
{
services.AddMvc();
services.AddDbContext<MyContext>();
}
刚刚在 MyContext 类中已经配置连接字符串了,所以注册服务时就不用指定连接字符串了。
按老周前面所写的博文,接下来是创建数据迁移,不过,这一次老周使用的是直接在运行的时候创建数据库,方法也是很简单的,找到 Main 入口点,把里面的代码改一下(项目模板默认生成的代码不进行大改)。
public static void Main(string[] args)
{
var host = CreateWebHostBuilder(args).Build();
using(IServiceScope scope= host.Services.CreateScope())
{
MyContext c = scope.ServiceProvider.GetService<MyContext>();
c.Database.EnsureCreated();
}
host.Run();
}
也就是在 host 运行之前,创建一个“作用域”级别的服务实例,创建数据库,这个实例是临时使用,不遵循服务容器的生命周期规则。EnsureCreated 方法会检测数据库是否存在,如果不存在,就创建,然后返回 true;如果数据库已经存在,不做任何处理并返回 false。
如果你不打算写入一些初始数据,可以不在乎方法的返回值,如果要写入初始数据,可以 if 一下,如果方法返回 true,就写一下数据进去(true 表示新数据库)。
接下来,咱们用一个 API 控制器来测试一下。
[Route("api/[action]")]
public class TestController : Controller
{
readonly MyContext context;
public TestController(MyContext c) => context = c;
[HttpPost]
public ActionResult AddNew([FromBody]Student stu)
{
……
}
[HttpGet]
public JArray GetList()
{
……
}
}
数据库上下文的实例因为已经注册到服务容器中,所以通过构造函数可以得到其实例引用。这个控制器有两个 action,AddNew 方法用来提交数据,以 POST 方式访问。
[HttpPost]
public ActionResult AddNew([FromBody]Student stu)
{
// 添加实体
context.Students.Add(stu);
// 设置影子属性
context.Entry(stu).Property<DateTime>("InsertTime").CurrentValue = DateTime.Now;
context.SaveChanges();
return Ok("操作成功");
}
记得,参数要加上 FromBody 特性,因为它要从 HTTP 消息正文中提取,上次我直播时就是忘了写这个,所以提交不到数据。
这里要注意影子属性的赋值方法,因为它没有在 Student 类中公开,你不能通过访问成员来设置它,只能先通过 CurrentValue 属性来设置。
然后还有一个 GetList 方法,以 GET 方式来访问。有来返回所有 Student 数据。此处我用 JArray 以 JSON 数组格式返回。
[HttpGet]
public JArray GetList()
{
var q = from s in context.Students
select new
{
s.Id,
s.Name,
s.Age,
// 读取影子属性值
InsertTime = EF.Property<DateTime>(s, "InsertTime")
};
JArray arr = new JArray();
foreach (var s in q)
{
JObject obj = new JObject();
obj.Add("id", new JValue(s.Id));
obj.Add("name", new JValue(s.Name));
obj.Add("age", new JValue(s.Age));
obj.Add("add_time", new JValue(s.InsertTime));
arr.Add(obj);
}
return arr;
}
读取影子属性的方法是用 EF.Property 静态方法,第一个参数是实体模型类的实例,第二个参数是影子属性的名字。这个方法只能在 LINQ 树中使用,如果不在 LINQ 中用会发生异常。这里还有一个问题,就是在 select 子句中用 new 返回的匿名类型无法创建 JObject 对象,所以只好手动去构建。
现在可以测一下了,首先提交一下数据。
{
"name":"李三跳",
"age":
}
接着获取一下数据列表。
[
{
"id": ,
"name": "什么鬼",
"age": ,
"add_time": "2018-11-26T11:15:38.2012809"
},
{
"id": ,
"name": "陈大扣",
"age": ,
"add_time": "2018-11-26T11:21:07.5374308"
},
{
"id": ,
"name": "李三跳",
"age": ,
"add_time": "2018-11-26T12:41:51.758849"
}
]
好了,示例就完成了。
影子属性的典型用法就像刚刚这个例子这样,可以用来记录数据的添加时间或者更新时间,但这种数据,一般不需要在实体模型中公开。
【ASP.NET Core】EF Core - “影子属性”的更多相关文章
- 国产化之路-统信UOS + Nginx + Asp.Net MVC + EF Core 3.1 + 达梦DM8实现简单增删改查操作
专题目录 国产化之路-统信UOS操作系统安装 国产化之路-国产操作系统安装.net core 3.1 sdk 国产化之路-安装WEB服务器 国产化之路-安装达梦DM8数据库 国产化之路-统信UOS + ...
- asp.net core+ef core
asp.net core+ef core 官方的文档https://docs.asp.net/en/latest/tutorials/first-mvc-app/start-mvc.html 先来看一 ...
- Asp.net Core + EF Core + Bootstrap搭建的MVC后台通用管理系统模板(跨平台版本)
Asp.net Core + EF Core + Bootstrap搭建的MVC后台通用管理系统模板(跨平台版本) 原创 2016年07月22日 10:33:51 23125 6月随着.NET COR ...
- .net core EF Core 视图的应用
由之前的一篇文章<.net core Entity Framework 与 EF Core>我们都已经知道 EF Core 增加了许多特性,并且性能上也有了很大的提升. 但是EF Core ...
- .net core EF Core 调用存储过程
在这里,我们将尝试去学习一下 .net core EF Core 中调用存储过程. 我们知道,EF Core 是不支持直接调用存储过程的,那它又提供了什么样的方式去执行存储过程呢?有如下方法: 1.F ...
- 在vs2015上使用asp.net core+ef core
官方的文档https://docs.asp.net/en/latest/tutorials/first-mvc-app/start-mvc.html 先来看一下实现的效果
- .Net Core EF Core之Sqlite使用及部署
1.添加引用Nuget包 Microsoft.EntityFrameworkCore.Sqlite Microsoft.EntityFrameworkCore.Design Microsoft.Ent ...
- asp.net Core EF core ( Entity Framework 7 ) 数据库更新维护
CreateDatabaseIfNotExists等之前的API已经废弃,现在采用的是微软封装好,简化.高效的API,migrations 因为,旧API,要付出高昂的代价,以及局限性 打开VS20 ...
- asp.net core-16.EF Core Migration
左边的是基于visual studio code 右边的是基于visual studio 如果想要在数据库的AspNetUsers表里添加一列 然后可以发现 在Data下的Migrations文件夹下 ...
- 个人搭建后台管理模板 Bootstrap4 ,ASP.NET Core,EF Core,JWT
拥有一个美观好用的网站后台,是很多开发者的梦想,笔者在闲暇时间里搭建了一个不错的后台框架,这里分享诸位开发同仁. 项目地址:https://github.com/kongdf123/KentNoteB ...
随机推荐
- 普林斯顿微积分读本 大纲与重点 (by zzd)
普林斯顿微积分读本 大纲重点 由于博客园太菜,所以我用图片上传. 当前更新状态:未完待续,挖坑暂时不填了. UPD(2018-07-08): 稍微更一下,加一个本书的某一版本下载链接:https:// ...
- jdk 生成证书
1.生成客户端的私钥,客户端的证书 1)keytool -genkey -alias clientkey -keystore kclient.keystore -validity 36500 2) ...
- python josn包
Python josn包中的编码与解码方法 对于Python数据类型进行编码解码 json.dumps 对python的数据类型进行json格式编码 :(将dict转为json格式) eg: imp ...
- 麒麟Kylin
开源的分布式分析引擎,提供Hadoop/Spark之上的SQL查询接口及多维分析(MOLAP)能力以支持超大规模数据,能在亚秒内查询巨大的Hive表: Kylin的主要特点包括支持SQL接口.支持超大 ...
- hdu1202解题报告
#include<stdio.h>int main(){ int n,i; double sum,s,p,sum1; while(scanf("%d" ...
- Sublime Text3搭建PHP开发环境
Sublime Text3搭建PHP开发环境 本文主要给大家分享了关于Sublime Text3搭建PHP开发环境 ,感兴趣的小伙伴可以做一下参考 一.Sublime text3安装 到官网http: ...
- 手动实现Promise
Promise对大家来说并不是很陌生,它是一个异步编程的解决方案,主要解决了前端回调地域问题.用阮老师的话说,它“就是一个容器,里面保存着某个未来才会结束的事件(通常是一个异步操作)的结果”. Pro ...
- Django 学习第三天——模板变量及模板过滤器
一.模板路径的查找: 查找顺序:(现在哪找到就用那个) 首先在主目录的 setting.py 文件里的 TEMPLATES 中的 DIRS 里找: 其次如果 DIRS 中的 APP_DIRS : 'T ...
- 上海市2019年公务员录用考试第一轮首批面试名单(A类)
上海市2019年公务员录用考试第一轮首批面试名单(A类) 注册编号 总成绩 注册编号 总成绩 注册编号 总成绩 注册编号 总成绩 4016574 127.4 5112479 145.9 5125732 ...
- vue实例属性之el,template,render
一.el,template,render属性优先性当Vue选项对象中有render渲染函数时,Vue构造函数将直接使用渲染函数渲染DOM树,当选项对象中没有render渲染函数时,Vue构造函数首先通 ...