Aleksej_Shherbak
Aleksej_Shherbak

Reputation: 3078

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

I have the following model:

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;
}

And the following application context:

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"));
    }
}

Next I will show you a screen of my PostgreSQL data base schema:

enter image description here

I'm trying to save a new entity with the help of the next code:

    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);
    }

But as the result I see this error. I don't understand why.

enter image description here

I absolutely sure that CreatedAtfield is not null during the saving. See a screen of debug:

enter image description here

Where is the mistake?

Upvotes: 1

Views: 2209

Answers (1)

Peter B
Peter B

Reputation: 24270

Your property indeed has a value, but it is also decorated with [DatabaseGenerated(DatabaseGeneratedOption.Computed)].

By using Computed, you are telling EF Core that it must leave the property's value upto the database. In other words, the database is made fully responsible for generating or computing a value during every query. As can be read here, "The practical effect of this is that Entity Framework will not include the property in INSERT or UPDATE statements".

The generated insert statement will then look like

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

Which will fail because CreatedAt has a NOT NULL setting, apparently without a default value.

You can try 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()");
}

This should work as long as it is supported for Npgsql, which I don't know for sure. If it does not work then you may have no other option but to remove the attribute and take value creation in your own hands.

Upvotes: 4

Related Questions