EF Core DatabaseGeneratedOption.Computed 不工作

Glo*_*ire 5 c# entity-framework entity-framework-core .net-core

我最近开始使用.NET CORE v2。我正在尝试通过在我的web-api模板中使用代码优先方法来设置我的数据库。

背景:我以前使用过 Laravel 框架,我想在迁移文件中复制 Laravel 的 timestamp() 函数,该函数基本上会在表中创建两列:UpdatedAt 和 CreatedAt。

当使用 INSERT 或 UPDATE 列的 ORM (Elqoquent) 函数时,这些列中的值会填充正确的值。它是无缝的,您无需担心。


在我的 c# 代码中,我有以下模型

public class A {
    [DatabaseGenerated(DatabaseGeneratedOption.Identity)]
    public int Id { get; set; }

    public string Name { get; set; }

    [DatabaseGenerated(DatabaseGeneratedOption.Identity)]
    public DateTime Created_At { get; set; } = DateTime.UtcNow;

    [DatabaseGenerated(DatabaseGeneratedOption.Computed)]
    public DateTime Updated_At { get; set; }

    // I've tried to add "= DateTime.UtcNow;" at the end of Updated_At as well
}
Run Code Online (Sandbox Code Playgroud)

我还有以下用于为数据库设置种子的类。

public static class DatabaseSeeder
{
    private static AppContext _context;

    public static void SeedDatabase(this AppContext appContext)
    {
        _context = appContext;
        _context.Database.EnsureCreated();

        // Verify if data exist.
        if (_context.A.Any())
        {
            return;
        }

        SeedAs();
    }

    private static void SeedAs()
    {
        var defaults = new A[]
        {
            new A
            {
                Name = "Value 1",
            },
            new A
            {
                Name = "Value 2",
            },
            new A
            {
                Name = "Value 3",
            }
        };

        _context.As.AddRange(defaults);
        _context.SaveChanges();
    }
}
Run Code Online (Sandbox Code Playgroud)

SeedDatabase 函数在 Startup 类的 Configure 函数中调用,如果数据库在启动时不包含任何数据,它基本上会为数据库播种。

问题:我遇到的问题是,当我第一次启动我的开发服务器时,应用程序注意到数据库不包含任何值,因此它尝试为它做种。返回以下错误:

MySql.Data.MySqlClient.MySqlException (0x80004005):字段“Updated_At”没有默认值

我似乎不明白为什么这会失败,因为当我通过删除 Updated_At 属性及其注释运行同一段代码时没有返回任何错误,并且数据库按预期播种了包含 DateTime.UtcNow 值的 Created_At 字段.

DatabaseGenerated(DatabaseGeneratedOption.Computed 注释) 的预期行为是根据插入或更新属性的数据类型生成数据库值。

谁能告诉我为什么,当我尝试为我的数据库做种时它失败了。

Tol*_*ela 1

首先,您已经在类中定义了 Created_At 的初始值:= DateTime.UtcNow;

这就是为什么它适用于Created_At但不适用于Updated_At。由于Updated_At没有初始值,并且数据库没有为此列定义任何默认值。

为了使其正常工作,您必须在 DbContext 类中定义 SQL 列的默认值。

我想,对于 MySQL 你应该使用函数NOW()

protected override void OnModelCreating(ModelBuilder modelBuilder)
{
    modelBuilder.Entity<A>()
            .Property(s => s.Created_At )
            .HasDefaultValueSql("NOW()");

    modelBuilder.Entity<A>()
            .Property(s => s.Updated_At )
            .HasDefaultValueSql("NOW()");
}
Run Code Online (Sandbox Code Playgroud)

文档:数据注释 - EF 6 和 EF Core 中的数据库生成属性

  • 这很有帮助,但对于使用 Microsoft SQL 的任何人来说,函数是 GETDATE() (4认同)