最近在做公司的项目的时候,开始把部分程序迁移到EF Core,然后有了一些感触,趁着还没忘却,还是先记录下来。

EF Core还在成长中,我写这个的时候,版本是2.2。如果对着已有的EF 5/6来说,还有很多功能要迎头赶上的,所以这个也是为什么在.net core 3的标准中,计划要支持EF 6(这个其实是一次性买卖),就是想让大家可以先把.net Core (EF6)用起来,让EF Core先缓口气,等它成长足够了,再迁移到.net Core (EF Core)这样的组合。

即便如此,现在版本的EF Core已经有好多不少的闪亮之处(当然也有一些会因为自己没学好而误会了它的坑)。不论是闪亮点,还是坑,我有时间的话,会缓缓道来。

Shadow Properties这个特性很好,值得先拿出来说一下。但是博客本来就不适宜写得长,不然就不适合碎片阅读。所以我会把它分开来写。而且我还可能会比较啰嗦,有骗字数的嫌疑。

Shadow properties are properties that are not defined in your .NET entity class but are defined for that entity type in the EF Core model. The value and state of these properties is maintained purely in the Change Tracker. (https://docs.microsoft.com/en-us/ef/core/modeling/shadow-properties)

简单地说,隐藏属性 (Shadow Properties),就是那些逻辑设计里面没有的,但是物理设计里面却要有的属性。逻辑设计 vs. 物理设计,是做面向对象编程的攻城狮,都需要面对的问题。例如,那些数据库自增长的ID,审计类字段,还有例如做数据库订阅所需要的时间戳等等。很绕口,让我说人话,就是我们的business class(业务类),是不会包括那些只对照某数据库,或者中间件才冒出来的神马ID之类的属性,而我们却可以在EF Core层面,搞定这些ID的安置方式,而不需要另外再弄一个新的EF class。

有了这个,我们就可以保持逻辑设计的干净,也可以省了再去多弄一个EF Class。或者干脆就着EF Class来细细捣弄(为了继续保持逻辑层的干净)。后述的两种手法,在我们灵活运用EF 5/6的时候,已经屡见不鲜了。

简单举个几个栗子(边幅所限,本篇先来一个个简单的,后面的继续举拖沓的栗子,继续骗字数)。例如,我们会在数据库有一些 LastUpdateBy (记录最后修改者/兼顾新增此记录建立者)、LastUpdateDate(记录最后改动的日期和时间)、CreatedDate(新增此记录的日期和时间)等等,提供简单审计记录功能的字段。但是,我们的Class里面,真心不想要这些属性。这个时候,我们可以继续保持原有business class不变。而在我们的DBContext class的OnModuleCreating方法中,针对某个需要有上述审计字段的Entity,加上这些Shadow Properties。下面的代码片段的例子,只支持UpdateDate和UpdateBy,CreateDate请自行脑补哈(Tips: EntityState.Added 状态下才更新此属性的值)。

public partial class MyDBContext : DbContext
{

protected override void OnModelCreating(ModelBuilder modelBuilder)
{

modelBuilder.Entity<MyEntity>(entity =>
{

addAuditingProperties(entity);
}
}
private void addAuditingProperties(EntityTypeBuilder builder)
{
builder.Property<DateTime?>("LastUpdateDate");
builder.Property<string>("LastUpdateBy");
}
private void setAuditingPropertyValues(EntityEntry entityEntry, string changedBy)
{
//请在调用Context.SaveChanges之前调用一次此方法

PropertyEntry propertyEntry;
if (
((propertyEntry = entityEntry.Properties.Where(e => e.Metadata.Name == "LastUpdateDate").FirstOrDefault()) != null) &&
(entityEntry.State == EntityState.Modified)
)
{
propertyEntry.CurrentValue = DateTime.UtcNow;
}
if (
((propertyEntry = entityEntry.Properties.Where(e => e.Metadata.Name == "LastUpdateBy").FirstOrDefault()) != null) &&
((entityEntry.State == EntityState.Modified) || (entityEntry.State == EntityState.Added))
)
{
propertyEntry.CurrentValue = changedBy;
}
...
}
...
}

很简单对吧?只需要偷偷地在自己的DBContext里面捣弄一下,根本不需要让上层建筑知道那么多,我们就支持了仅在数据表里面才有的审计类字段。

接下来,下一篇,会举一个更啰嗦的栗子。解释一下,为什么我们的business class,不应该有那些由于物理设计(落地选型)所带出来的各式各样的神马ID,以及怎么用Shadow Properties来支持。但是因为这个涉及到asp.net core web api的相应改动,所以值得另开一个帖子来骗字数了。

下次见哈。

Shadow Properties之美(一)【Microsoft Entity Framework Core随笔】的更多相关文章

  1. Shadow Properties之美(二)【Microsoft Entity Framework Core随笔】

    接着上一篇Shadow Properties之美(一),我们来继续举一个有点啰嗦的栗子. 先看简单需求:某HR系统,需要记录员工资料.需要记录的资料有: 员工号(规则:分公司所在城市拼音首字母,加上三 ...

  2. “幕后英雄”之Backing Fields【Microsoft Entity Framework Core随笔】

    刘德华 有一首歌叫<马桶>,其中有一句歌词是:每一个马桶都是英雄. EFCore也有一个英雄,在幕后默默地任劳任怨.它就叫 "支持字段" (Backing Fields ...

  3. Entity Framework Core 1.1 Preview 1 简介

    实体框架核心(EF Core)是Entity Framework的一个轻量级,可扩展和跨平台版本. 10月25日,Entity Framework Core 1.1 Preview 1发布了. 升级到 ...

  4. Working with Data » Getting started with ASP.NET Core and Entity Framework Core using Visual Studio » 创建复杂数据模型

    Creating a complex data model 创建复杂数据模型 8 of 9 people found this helpful The Contoso University sampl ...

  5. Working with Data » Getting started with ASP.NET Core and Entity Framework Core using Visual Studio » 排序、筛选、分页以及分组

    Sorting, filtering, paging, and grouping 7 of 8 people found this helpful By Tom Dykstra The Contoso ...

  6. Working with Data » 使用Visual Studio开发ASP.NET Core MVC and Entity Framework Core初学者教程

    原文地址:https://docs.asp.net/en/latest/data/ef-mvc/intro.html The Contoso University sample web applica ...

  7. Professional C# 6 and .NET Core 1.0 - 38 Entity Framework Core

    本文内容为转载,重新排版以供学习研究.如有侵权,请联系作者删除. 转载请注明本文出处:Professional C# 6 and .NET Core 1.0 - 38 Entity Framework ...

  8. Entity Framework Core 生成跟踪列

    本文翻译自<Entity Framework Core: Generate tracking columns>,由于水平有限,故无法保证翻译完全正确,欢迎指出错误.谢谢! 注意:我使用的是 ...

  9. Professional C# 6 and .NET Core 1.0 - Chapter 38 Entity Framework Core

    本文内容为转载,重新排版以供学习研究.如有侵权,请联系作者删除. 转载请注明本文出处:Professional C# 6 and .NET Core 1.0 - Chapter 38 Entity F ...

随机推荐

  1. 软件测试2gkd

    JUnit单元测试 一.单元测试的概念和目的 什么是单元测试?单元测试是在开发过程中要进行的最低级别的测试活动,是需要与开发同步进行的工作,它由程序员自己完成,属于编码的一部分.单元测试是为了确保类的 ...

  2. Use SourceLink enables a great source debugging experience

    posts Exploring .NET Core's SourceLink - Stepping into the Source Code of NuGet packages you don't o ...

  3. pronaunciation

    5 strong  weak s            d n            t l             th you and I  -> you an dai -> you ...

  4. react-native webView android使用本地html问题

    react-native WebView组件使用本地html时候,一般都是这样使用 var source = require('../html/my.html') : <WebView sour ...

  5. 【Redis】windows下redis服务的安装

    下载地址: https://github.com/MicrosoftArchive/redis/releases Redis 支持 32 位和 64 位.这个需要根据你系统平台的实际情况选择,这里我们 ...

  6. openssl 生成pfx

    证书可以通过几种渠道获得, 可以购买, 可以使用IIS生成, 也可以使用Openssl这样的工具生成证书. 本篇文章主要介绍openssl生成pfx文件 首选去网关下载openssl 下载地址:htt ...

  7. Redis(三)-数据类型

    1.五种数据类型:字符串类型.字符串列表.有序字符串集合.哈希.字符串集合 2.字符串类型常用操作 (1)赋值 $ set key value (2)取值 $ get key (3)删除 $ del ...

  8. [Database]Oracle数据库中concat和||的区别

    注:在oracle中,需要上述多次拼接应使用||,因为concat()一次只能拼接2个,需要多次嵌套.而在mysql中,可以实现concat(col1,col2,coln....) 官方文档链接:CO ...

  9. 基于apache的虚拟主机

    apche支持3种类型虚拟主机: 基于IP的虚拟主机 基于端口的虚拟主机 基于主机名的虚拟主机 配置两个站点虚拟主机: /data/web1 /data/web2 一.基于IP虚拟主机 添加一个IP: ...

  10. VS 2017 创建类注释模板

    在VS 2017/2019等 同样打开下方路径 C:\Program Files (x86)\Microsoft Visual Studio\2017\Enterprise\Common7\IDE\I ...