如何指示 EF Core 在更新/SaveChanges 期间获取 CreatedAt 列的值

问题描述 投票:0回答:1

我有一个这样的模型:

class Client 
{
    public int id {get; set;}
    ...
    public DateTime CreatedAt {get; set;}
}

具有以下类型配置(所有其他字段都有默认配置):

builder.Property(p => p.CreatedAt)
    .HasDefaultValueSql("now() at time zone 'utc'")
    .ValueGeneratedOnAdd()    .Metadata.SetAfterSaveBehavior(Microsoft.EntityFrameworkCore.Metadata.PropertySaveBehavior.Ignore);

当我执行更新操作时,我不想提供 CreatedAt 值,即我希望它始终保持不变,因此在我的 API 联系人中,我什至不接受 PUT(更新)端点的 CreatedAt 值。 我想要的是在更新期间忽略 CreatedAt 字段,这就是 Metadata.SetAfter... 的原因。但是,在 SaveChanges() 之后,CreatedAt 字段保持为空/默认值。

我想以某种方式指示 EF Core 在更新操作期间获取 CreatedAt 字段的值,即使我不更新它。有什么办法可以实现吗?

我知道可以使用类似 Reload() 的方法来重新加载所有字段,但这意味着对于 1 个更新操作,应用程序将始终对数据库执行 2 个请求。第二个请求的唯一原因只是为了获取 CreatedAt 字段的值,这对我来说听起来不太好。

c# .net entity-framework asp.net-core entity-framework-core
1个回答
0
投票

插入时将填充 CreatedAt 字段。更新永远不会改变它。正常的更新操作应该从修改后的 DTO/Viewmodel 中获取并更新实体属性,以便您在该时间点获得 CreatedAt。由于这是一个计算属性,因此您应该保护 setter,因为代码永远不能更改 CreatedAt 时间戳:

 public DateTime CreatedAt {get; protected set;}

从那里我将删除元数据。 从那里插入新实体后,应在保存后填充 CreatedAt 值。对于更新操作,请避免使用

Update
方法,例如:

var order = new Order { Id = orderId, .... };
_context.Update(order);
_context.SaveChanges();

或更糟糕的是,在控制器操作中,使用从客户端实现的实体来调用

Update()
传递分离的实体。您应该避免这种方法的原因是它可能容易发生数据篡改(以您不期望的方式更改请求并覆盖不应更改的数据),并且
Update()
会为所有(非即使值没有更改,每次也会生成)列。通过使用 EF 的更改跟踪和复制值,您可以获得以下好处:

确保更新行存在且有效。
  • 仅复制允许更改的值。
  • 仅当至少有一个值实际发生变化时,才为实际更改的值生成
  • UPDATE
  • SQL 语句。
    
    
  • .

UPDATE

为了帮助避免一次手动复制一个属性,您可以使用 Automapper 或 Mapperly 等映射器来定义执行更新时可以复制的允许映射。 IE。如果只需要编辑 6 个字段,您可以确保只复制这 6 个可能的值。

© www.soinside.com 2019 - 2024. All rights reserved.