使用 Fluent API 计算更新和插入字段

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

我正在尝试在模型中配置一个字段,该字段将通过插入和更新进行修改。

我尝试了多种方法,但仍然可以找到满足我的要求的正确配置。

示例:

public class Author
{
    public DateTime UpdatedAt { get; set; } 
}

我有一个字段

UpdatedAt
,当插入/更新一行时,该字段将在 SQL Server 端计算。

到目前为止我已经尝试过以下

  1. 我尝试过这样的数据注释,但没有满足要求。

     public class Author
     {
         [DatabaseGenerated(DatabaseGeneratedOption.Computed)]
         public DateTime UpdatedAt { get; set; } 
     }
    
  2. 我尝试了这样的数据注释和设置默认值,但没有满足要求。

     public class Author
     {
         [DatabaseGenerated(DatabaseGeneratedOption.Computed)]
         public DateTime UpdatedAt { get; set; }  = DateTime.UtcNow;
     }
    
  3. 我尝试了Fluent API,但不符合要求,它是在插入时设置值,但在更新时不修改它。

     modelbuilder.Entity<Author>()
                 .Property(a => a.UpdatedAt)
                 .HasDefaultValueSql("GetUtcDate()")
                 .ValueGeneratedOnAddOrUpdate();
    
  4. 我又尝试了Fluent API,但没有达到要求。既不设置值也不修改它。

     modelbuilder.Entity<Author>()
                 .Property(a => a.UpdatedAt)
                 .ValueGeneratedOnAddOrUpdate();
    
  5. 我又尝试了Fluent API,但没有达到要求。当有插入或更新时,它会更新该列的所有行。

     modelbuilder.Entity<Author>()
                 .Property(a => a.UpdatedAt)
                 .HasComputedColumnSql("GetUtcDate()");
    
c# entity-framework ef-fluent-api
1个回答
1
投票

我不是 EF 专家,但根据 documentation,更新时生成的日期时间值需要通过触发器创建(这与我对 SQL Server 的了解一致)。

在 SQL Server 中,执行此操作的方法是编写一个用于插入和更新的触发器,该触发器将更新指定的列。

但是请注意,文档中提供的触发器示例存在缺陷,因为它假设仅进行单行更新。在 SQL Server 中,触发器是根据语句而不是行触发的,因此当您更新多行(或 EF 中的实例)时,触发器将被触发一次。
所以正确的写法是这样的

CREATE TRIGGER [dbo].[Author_UPDATE] ON [dbo].[Author]
    AFTER UPDATE
AS
BEGIN
    SET NOCOUNT ON;

    IF ((SELECT TRIGGER_NESTLEVEL()) > 1) RETURN;

    UPDATE A
    SET UpdatedAt = GETDATE()
    FROM Author As A
    INNER JOIN Inserted As I
        ON A.Id = I.Id;
END

或者,您可以处理

DbContext.SavingChanges
事件来更改要保存的所有实体中
UpdatedAt
的值,如 EF Core 中的 .NET 事件 文档页面中的此示例所示。

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