Npgsql,保存 DateTime 值时出错(列 "CreatedAt" 中的空值违反了非空约束)

Npgsql, error during saving a DateTime value (null value in column "CreatedAt" violates not-null constraint)

我有以下型号:

public class Product
{
    public int Id { get; set; }

    public string Name { get; set; }

    public string Description { get; set; }

    public string Category { get; set; }

    public decimal Price { get; set; }

    [DatabaseGenerated(DatabaseGeneratedOption.Computed)]
    [ScaffoldColumn(false)]
    public DateTime CreatedAt { get; set; } = DateTime.Now;
}

以及以下应用上下文:

public class ApplicationContext : DbContext
{
    private readonly string _connectionString;

    public DbSet<Product> Products { get; set; }

    public ApplicationContext(IConfiguration configuration)
    {
        _connectionString = configuration.GetConnectionString("Sportshop");
    }

    protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
    {
        optionsBuilder.UseNpgsql(_connectionString, b => b.MigrationsAssembly("Web"));
    }
}

接下来我将向您展示我的 PostgreSQL 数据库模式的屏幕:

我正在尝试借助下一个代码保存新实体:

    public ViewResult Index()
    {
        Product product = new Product
        {
            Name = "P1",
            Category = "test",
            Price = 1000,
            Description = "Hello !!!"
        };

        _applicationContext.Products.Add(product);
        _applicationContext.SaveChanges();


        return View(// ... some view data);
    }

但结果我看到了这个错误。我不明白为什么。

我绝对确定CreatedAt字段在保存过程中不为空。查看调试屏幕:

哪里错了?

你的属性确实有值,但也是用[DatabaseGenerated(DatabaseGeneratedOption.Computed)]装饰的。

通过使用 Computed,您告诉 EF Core 它必须将 属性 的值留给数据库。换句话说,数据库完全负责在每次查询期间生成或计算值。可以读到 here,“ 这样做的实际效果是 Entity Framework 将不会在 INSERT 或 UPDATE 语句 中包含 属性”。

生成的插入语句将类似于

INSERT INTO Products (Id, Name, Description, Category, Price) ...

这将失败,因为 CreatedAt 有一个 NOT NULL 设置,显然没有默认值。

你可以试试giving the field a default value using the Fluent API:

protected override void OnModelCreating(ModelBuilder modelBuilder)
{
    modelBuilder.Entity<Product>()
        .Property(b => b.CreatedAt)
        .HasDefaultValueSql("getdate()");
}

只要 Npgsql 支持它就应该可以工作,我不确定。如果它不起作用,那么您可能别无选择,只能删除该属性并自行创造价值。