Entity Framework Core 生成跟踪列

注意:我使用的是 Entity Framework Core 2.0 (2.0.0-preview2-final)。正式版发布时,功能可能存在变动。

当您设计数据库时,有时需要添加列以跟踪记录何时更改,以及谁进行了更改。例如,您添加以下列:

  • CreatedAt

  • CreatedBy

  • LastUpdatedAt

  • LastUpdatedBy

您可以 轻松 地使用默认值和触发器来处理CreatedAtLastUpdatedAt列。老实说,创建触发器是件无聊的事情,你也不想自己做。此外,很难设置用户名,因为它是应用程序的信息;实际上,在Web程序的上下文中,它们只是连接到数据库的一个用户,因此,您无法使用数据库中CURRENT_USER函数设置跟踪列的值。

当然,您不想访问这个属性。相反,您希望 Entity Framework 为您自动执行,所以,解决的办法是调用SaveChangesSaveChangesAsync方法之前自动设置这些属性的值。在模型中有多种方法处理这些属性:您可以在模型中添加读写(R/W)属性;您也可以使用只读(R/O)属性;还有一种方案,您可以使用阴影(Shadow)属性。在最后一种方案中,是将列不映射到模型中的属性,只有 Entity Framework 才知道这些属性。是的,EF Core 非常灵活:)

我们用 Entity Framework 实现这3种方案!

读写属性

在这种情况下,实体将具有读/写属性。这意味着,您可以在代码中更改属性的值。

public interface ITrackable{
 DateTime CreatedAt { get; set; }  
 string CreatedBy { get; set; }DateTime LastUpdatedAt { get; set; }  
 
  string LastUpdatedBy { get; set; } }
  public class Post : ITrackable{    
  public int Id { get; set; }  
    public string Title { get; set; }  
     public string Content { get; set; }
        public DateTime CreatedAt { get; set; }
           public string CreatedBy { get; set; }  
            public DateTime LastUpdatedAt { get; set; }  
              public string LastUpdatedBy { get; set; } }

现在,我们将更改SaveChanges方法的默认行为来设置跟踪属性的值。要小心,有两个方法要重写:SaveChanges和异步方法SaveChangesAsync。在代码中遍历上下文中跟踪的实体,并根据状态设置跟踪属性的值。代码非常简单:

public class BloggingContext : DbContext{  

 public DbSet<Post> Posts { get; set; }  
 
   public override int SaveChanges(bool acceptAllChangesOnSuccess)    {OnBeforeSaving();    
      return base.SaveChanges(acceptAllChangesOnSuccess);}
   public override Task<int> SaveChangesAsync(bool acceptAllChangesOnSuccess, CancellationToken cancellationToken = default(CancellationToken))    {OnBeforeSaving();      
     return base.SaveChangesAsync(acceptAllChangesOnSuccess, cancellationToken);}  
     
    private void OnBeforeSaving()    {      
      var entries = ChangeTracker.Entries();      
        foreach (var entry in entries){          
         if (entry.Entity is ITrackable trackable){              
          var now = DateTime.UtcNow;        
                 var user = GetCurrentUser();        
               switch (entry.State){                
                  case EntityState.Modified:trackable.LastUpdatedAt = now;trackable.LastUpdatedBy = user;    
                                     break;      
                   case EntityState.Added:trackable.CreatedAt = now;trackable.CreatedAt = user;trackable.LastUpdatedAt = now;trackable.LastUpdatedBy = user;                        break;}}}}  
    
     private string GetCurrentUser()    {             
            return "UserName"; // TODO implement your own logic} }

这个方案有个不容忽视的问题,属性是可写的,您不希望在代码中设置属性的值。让我们看看如何使用只读属性。

只读属性

Entity Framework Core 允许将列映射到字段。这样,您可以使用只读属性,我们来修改 Post类:

public class Post{   
 private DateTime _createdAt;  
   private string _createdBy;  
    private DateTime _lastUpdatedAt;  
      private string _lastUpdatedBy;  
        public int Id { get; set; }
        public string Title { get; set; }
        public string Content { get; set; }  
        public DateTime CreatedAt => _createdAt;
        public string CreatedBy => _createdBy;  
        public DateTime LastUpdatedAt => _lastUpdatedAt;  
        public string LastUpdatedBy => _lastUpdatedBy; }

上面的代码有点麻烦,但属性现在是只读的。您需要指引 Entity Framework 使用这些字段来设置列的值。

public class BloggingContext : DbContext{   

 public DbSet<Post> Posts { get; set; }  
  protected override void OnModelCreating(ModelBuilder modelBuilder)    {        base.OnModelCreating(modelBuilder);modelBuilder.Entity<Post>().Property(post => post.CreatedAt).HasField("_createdAt");modelBuilder.Entity<Post>().Property(post => post.CreatedBy).HasField("_createdBy");modelBuilder.Entity<Post>().Property(post => post.LastUpdatedAt).HasField("_lastUpdatedAt");modelBuilder.Entity<Post>().Property(post => post.LastUpdatedBy).HasField("_lastUpdatedBy");} }

您不能像以前那样实现OnBeforeSaving方法,因为属性没有setter。不过,您可以使用 ChangeTracker来指引 Entity Framework 为属性设置值。这种方式无需访问属性或字段。

    private void OnBeforeSaving()    {    
       var entries = ChangeTracker.Entries();    
       foreach (var entry in entries){        
          if (entry.Entity is Post post){              
              var now = DateTime.UtcNow;        
              var user = GetCurrentUser();          
               switch (entry.State){                  
                case EntityState.Modified:entry.CurrentValues["LastUpdatedAt"] = now;entry.CurrentValues["LastUpdatedBy"] = user;                        break;                
                    case EntityState.Added:entry.CurrentValues["CreatedAt"] = now;entry.CurrentValues["CreatedBy"] = user;entry.CurrentValues["LastUpdatedAt"] = now;entry.CurrentValues["LastUpdatedBy"] = user;                        break;}}}} }

我认为应是使用的方式,因为这种方式很清晰。

不定义属性

在某些情况下,您可能需要设置列的值而不在模型中定义属性。例如,您可能会公开最后更新的日期,但不会显示谁做了更改。Entity Framework Core 可以通过使用阴影(Shadow )属性来处理这个。阴影属性在OnModelCreating方法中声明,但在类中不存在。您可以使用ChangeTracker读取和写入阴影属性的值。

public class Post{   
    public int Id { get; set; }  
     public string Title { get; set; }  
     public string Content { get; set; } }
public class BloggingContext : DbContext{  

 protected override void OnModelCreating(ModelBuilder modelBuilder)    {        base.OnModelCreating(modelBuilder);      
   // Declare propertiesmodelBuilder.Entity<Post>().Property<DateTime>("CreatedAt");modelBuilder.Entity<Post>().Property<string>("CreatedBy");modelBuilder.Entity<Post>().Property<DateTime>("LastUpdatedAt");modelBuilder.Entity<Post>().Property<string>("LastUpdatedBy");}  
   
    private void OnBeforeSaving()    {      
    var entries = ChangeTracker.Entries();    
       foreach (var entry in entries){      
            if (entry.Entity is Post post){            
                var now = DateTime.UtcNow;            
      var user = GetCurrentUser();        
             switch (entry.State){                  
               case EntityState.Modified:entry.CurrentValues["LastUpdatedAt"] = now;entry.CurrentValues["LastUpdatedBy"] = user;                        break;                
                   case EntityState.Added:entry.CurrentValues["CreatedAt"] = now;entry.CurrentValues["CreatedBy"] = user;entry.CurrentValues["LastUpdatedAt"] = now;entry.CurrentValues["LastUpdatedBy"] = user;                        break;}}}} }

总结

使用 Entity Framework Core,您可以根据需求将数据库表映射到对象模型。这允许创建干净的类,不需要公开您不想要的属性。Very nice :)

原文地址:http://www.cnblogs.com/tdfblog/p/entity-framework-core-generate-tracking-columns.html


.NET社区新闻,深度好文,微信中搜索dotNET跨平台或扫描二维码关注

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/324475.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

老师,我们想看到您的笑容!

“老师&#xff0c;你可以对我们笑笑吗&#xff1f;”今天偶然遇见一位学生在吃饭的路上和我说道。我冲他点了点头&#xff0c;笑道&#xff1a;“好呀”&#xff01;是啊&#xff0c;我是好久没有把笑声带回班级中了。1目前&#xff0c;4班都在倾尽全力的做项目&#xff0c;试…

阿里巴巴开源 Spring Cloud Alibaba,加码微服务生态建设

转载自 阿里巴巴开源 Spring Cloud Alibaba&#xff0c;加码微服务生态建设 本周&#xff0c;Spring Cloud联合创始人Spencer Gibb在Spring官网的博客页面宣布&#xff1a;阿里巴巴开源 Spring Cloud Alibaba&#xff0c;并发布了首个预览版本。随后&#xff0c;Spring Cloud…

微软发布Azure Stack更多细节,预计9月交付

在近日举行的微软全球合作伙伴大会上&#xff0c;微软宣布Azure Stack现在开始接受预定&#xff0c;预计9月份就可以交付。Azure Stack是微软公有Azure云的私有云实现。和其他私有云提供商不同&#xff0c;微软将把Azure Stack作为一项基于消费的服务&#xff0c;这和其公有云的…

今天你们表现的真棒!!!

12月5日在报告厅举行了“2020级青鸟4班 HTML网页设计大赛”。从一个洁白如纸的空白页面&#xff0c;到布满五彩斑斓样式的cool页面&#xff0c;是同学们一个字母一个单词的敲打出来的。从头脑空白啥都不会说到现在的条理清晰张嘴就来的演讲&#xff0c;是同学们时时刻刻写稿子背…

再有人问你Netty是什么,就把这篇文章发给他

转载自 再有人问你Netty是什么&#xff0c;就把这篇文章发给他 本文基于Netty4.1展开介绍相关理论模型&#xff0c;使用场景&#xff0c;基本组件、整体架构&#xff0c;知其然且知其所以然&#xff0c;希望给大家在实际开发实践、学习开源项目提供参考。 这是一篇万字长文&a…

SpringCloud Netflix Hystrix

文章目录一、 Hystrix简介1 什么是灾难性雪崩效应2 什么是Hystrix二、 服务降级(Ribbon中)三、 服务熔断(Ribbon中)&#xff08;服务降级的强化版&#xff09;四、 请求缓存(Ribbon中)(不推荐)(查询频率高&#xff0c;修改频率低时谨慎使用)五、 Openfeign的雪崩处理1 服务降级…

[信息安全] 3.HTTPS工作流程

0. 简单回顾 在前面两篇博客中介绍了密码相关的一些基本工具&#xff0c;包括&#xff08;对称密码&#xff0c;公钥密码&#xff0c;密码散列函数&#xff0c;混合密码系统&#xff0c;消息认证码码&#xff0c;数字签名&#xff0c;伪随机数&#xff0c;数字证书&#xff09…

如何实现省市关联的下拉列表

前言&#xff1a;在某些电商网站或者APP中&#xff0c;通常填写地址时&#xff0c;会有这样的功能&#xff1a;当我们选择的省份是“山东”时&#xff0c;则城市的下拉列表里所展示的便是山东的城市&#xff0c;当选择的省份是“山西”时&#xff0c;城市的下拉列表所展示的便是…

什么样的事才是有意义的

有时候就在想&#xff0c;真正什么样的事才算有意义呢&#xff1f;

在Azure Container Service创建Kubernetes(k8s)群集运行ASP.NET Core跨平台应用程序

引子 在此前的一篇文章中&#xff0c;我介绍了如何在本地docker环境中运行ASP.NET Core跨平台应用程序&#xff0c;看起来非常不错&#xff0c;不是吗&#xff1f;那么&#xff0c;如果我们希望真正在实际的生产环境去部署和运行这个应用程序&#xff0c;应该怎么做呢&#xf…

这也许是你不曾留意过的 Mybatis 细节

转载自 这也许是你不曾留意过的 Mybatis 细节 Mybatis 可以说是 Java 后端的必备技能&#xff0c;可能你和我一样经常使用到它。但有时 cv 多了&#xff0c;会忘记了一些细节处理&#xff0c;比如为什么要加上这个注解&#xff1f;它的作用是什么等等。 这篇文章是我以前写的…

Nacos整合Ribbon实现客户端负载均衡

启动类去掉RibbonClient注解 10 50 100 1 权重优先调用 注意:启动类加RibbonClient注解 2 集群优先调用 3 元数据基于版本优先调用

ssl1344-Knights【最大独立集,最大匹配,图论】

正题 大意 求在一个扣掉m个格子的n*n的棋盘能放置的最多的马。 解题思路 求最大独立集就好了&#xff0c;最大独立集点数-最大匹配数。最重要的是如何建图。定义一个数组point[i][j]表示点的编号。但是如果这样的话就会O(n4)O(n4)就会超时。现在我们把棋盘从左到右后从上到…

小课堂?小视频?小商店?

今天&#xff0c;没有什么特别内容可更新&#xff0c;就来随便聊聊吧。01雄雄的小课堂这是一个公众号&#xff0c;内容主要有两大类。一类是以分享编程技术为主&#xff0c;一方面是为了提升自己&#xff0c;另一方面也是为了帮助别人&#xff0c;希望阅者有益&#xff0c;平时…

Entity Framework Core 软删除与查询过滤器

注意&#xff1a;我使用的是 Entity Framework Core 2.0 (2.0.0-preview2-final)。正式版发布后&#xff0c;功能可能存在变动。 继续探索Entity Framework Core 2.0&#xff0c;今天我将探讨如何轻松使用软删除&#xff08;或逻辑删除&#xff09;。我的意思是以透明的方式实…

相比学习好的学生,老师最喜欢努力认真学习的学生

相比学习好的学生&#xff0c;老师还是更喜欢努力学习的学生。好多人有这样的错觉&#xff0c;谁学习好&#xff0c;老师就喜欢谁&#xff0c;谁就是老师面前的大红人&#xff0c;可能有的老师是这样的吧&#xff0c;但是&#xff0c;对于我来说&#xff0c;相比那些学习好的学…

Postgresql快速写入\/读取大量数据(.net)

环境及测试 使用.net驱动npgsql连接post数据库。配置&#xff1a;win10 x64, i5-4590, 16G DDR3, SSD 850EVO. postgresql 9.6.3&#xff0c;数据库与数据都安装在SSD上&#xff0c;默认配置&#xff0c;无扩展。 CREATE TABLE public.mesh (x integer NOT NULL,y integer N…

mybatis更新Blob类型字段要用updateByPrimaryKeyWithBLOBs

转载自 mybatis更新Blob类型字段要用updateByPrimaryKeyWithBLOBs 不会报错也不会更新desc 业务desc数据库类型为Blob 查看源码 解决方案:

Ajax实现动态及时刷新表格数据

大家好&#xff0c;我是雄雄&#xff0c;今天分享的技术很简单&#xff0c;即ajax结合jdbc动态实现及时刷新表单数据。前言&#xff1a;相信大家在网上冲浪的时候&#xff0c;肯定会发现这样的场景&#xff0c;在实现某个查询功能时&#xff0c;下方表格中会显示需要展示的结果…