Marqueone
Marqueone

Reputation: 1213

EntityFramework Core 2 Default Values

I'm trying to use default values on a couple of my EF models and I'm noticing that either I'm misunderstanding the HasDefaultValue behaviour or its not working as it should.

I have the following table and backing model

CREATE TABLE [dbo].[packages]
(
   [Scnumber] BIGINT NOT NULL, 
   [PU] INT NOT NULL,
   [State] SMALLINT NOT NULL DEFAULT 0, 
   [Status] [smallint] NOT NULL, 
   [Created] DATETIME NOT NULL DEFAULT GETDATE(), 
   CONSTRAINT [PK_packages] PRIMARY KEY CLUSTERED ([Scnumber] ASC) ON [PRIMARY], 
)

[Table("packages", Schema = "dbo")]
public class Package
{
   [Key]
   [Column(TypeName = "bigint")]
   public long Scnumber { get; set; }

   [Column]
   [Required]
   public int PU { get; set; }

   [Column(TypeName = "smallint")]
   [Required]
   public PackageStatus Status { get; set; }

   [Column(TypeName = "tinyint")]
   public RecordState State { get; set; }

   [Column]
   public DateTime? Created { get; set; }    
}

In order to apply default values I've also got the following in my OnModelCreating()

modelBuilder.Entity<Package>(entity =>
{
   entity.Property(r => r.State)
      .HasDefaultValue(RecordState.Active);

   entity.Property(r => r.Created)
      .HasDefaultValue(DateTime.Now);
});

When I attempt to save a new object I get the following exception:

SqlException: Cannot insert the value NULL into column 'State', table 'app.dbo.packages'; column does not allow nulls. INSERT fails.

This is confusing as if I inspect the object before I save it, it has a default value, but yet I get this exception. I understand the easiest solution would be to simply make sure I set the value of state when I create the object, but this sort of defeats the purpose of HasDefaultValue.

-- edit --

When I try to add a new object I do the following

var package = new Package { Scnumber = 0123456718, PU = 1001 };

_context.Packages.Add(region);
_context.SaveChanges();

Nothing about this is out of the norm but fails, but if I run the following it works

var package = new Package {Scnumber = 0123456718, PU = 1001, Status = PackageStatus.Rejected, State = RecordState.Staging, Created = DateTime.Now };

_context.Packages.Add(region);
_context.SaveChanges();

public enum PackageStatus : short
{
   New,
   PendingValidation,
   CheckedOut,
   Approved,
   Rejected,
   PendingRender,
   Rendered,
   RenderFailed,
   PendingPrint,
   Printed,
   PrintFailed,
   Cancelled,
   PendingDownload,
   Downloaded,
   DownloadError,
   SystemUpdated, 
}

public enum RecordState : byte
{
    Active,
    Deleted,
    Staging,
}

Upvotes: 9

Views: 32546

Answers (2)

Lapenkov Vladimir
Lapenkov Vladimir

Reputation: 3218

I encountered the same issue. After updates in OnModelCreating you have to apply migration to database. Write dotnet ef migrations add defaultValuesAddedToPackage and then dotnet ef database update. This makes default value on column type so you don't need to explicitely set in your new entity or in sql insert. If you write dotnet ef migrations script you see code something like ALTER TABLE [packages] ADD DEFAULT 0 FOR [State];

Upvotes: 1

Matheus Lacerda
Matheus Lacerda

Reputation: 6007

I have a .HasDefaultValueSql("((0))") working in my current project.

Also found .HasDefaultValueSql("getdate()") and .HasDefaultValue(3); here.

Upvotes: 12

Related Questions