TransWikia.com

Scaffold-DbContext doese not add [DatabaseGenerated(DatabaseGeneratedOption.Computed)] on Generated class

Stack Overflow Asked on December 1, 2021

I am using EF Core 3.1 with a database-first approach using Linq-to-Entities.
but when I cerate my models with this code

Scaffold-DbContext "Server=xxxx;Database=xx;Trusted_Connection=True;Integrated security=false;User id=xx;Password=xx;" Microsoft.EntityFrameworkCore.SqlServer -f -OutputDir Models

it does not add proper [DatabaseGenerated(DatabaseGeneratedOption.Computed)] on generated class properties with default values.

this is my table Script :

CREATE TABLE [dbo].[member](
    [id] [bigint] IDENTITY(1,1) NOT NULL,
    [fName] [nvarchar](20) NOT NULL,
    [lName] [nvarchar](30) NOT NULL,
    [gender] [bit] NOT NULL,
    [birthDate] [date] NULL,
    [education] [tinyint] NOT NULL,
    [province] [tinyint] NOT NULL,
    [image] [nvarchar](200) NOT NULL,
 CONSTRAINT [PK_Member] PRIMARY KEY CLUSTERED 
(
    [id] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]

GO

SET ANSI_PADDING OFF
GO

ALTER TABLE [dbo].[member] ADD  CONSTRAINT [DF_member_gender]  DEFAULT ((0)) FOR [gender]
GO

ALTER TABLE [dbo].[member] ADD  CONSTRAINT [DF_member_birthDate]  DEFAULT (NULL) FOR [birthDate]
GO

ALTER TABLE [dbo].[member] ADD  CONSTRAINT [DF_member_education]  DEFAULT ((1)) FOR [education]
GO

ALTER TABLE [dbo].[member] ADD  CONSTRAINT [DF_member_province]  DEFAULT ((1)) FOR [province]
GO

ALTER TABLE [dbo].[member] ADD  CONSTRAINT [DF_member_image]  DEFAULT ('') FOR [image]
GO

ALTER TABLE [dbo].[member]  WITH CHECK ADD  CONSTRAINT [FK_Member_education] FOREIGN KEY([education])
REFERENCES [dbo].[education] ([id])
GO

ALTER TABLE [dbo].[member] CHECK CONSTRAINT [FK_tblMember_education]
GO

ALTER TABLE [dbo].[member]  WITH CHECK ADD  CONSTRAINT [FK_Member_Province] FOREIGN KEY([province])
REFERENCES [dbo].[province] ([id])
GO

ALTER TABLE [dbo].[member] CHECK CONSTRAINT [FK_Member_Province]
GO

One Answer

When scaffolding the database (without the --data-annotations option), the following Fluent API calls get generated, including the corresponding .HasDefaultValueSql() calls:

protected override void OnModelCreating(ModelBuilder modelBuilder)
{
    modelBuilder.Entity<Member>(entity =>
    {
        entity.ToTable("member");

        entity.Property(e => e.Id).HasColumnName("id");

        entity.Property(e => e.BirthDate)
            .HasColumnName("birthDate")
            .HasColumnType("date");

        entity.Property(e => e.Education)
            .HasColumnName("education")
            .HasDefaultValueSql("((1))");

        entity.Property(e => e.FName)
            .IsRequired()
            .HasColumnName("fName")
            .HasMaxLength(20);

        entity.Property(e => e.Gender).HasColumnName("gender");

        entity.Property(e => e.Image)
            .IsRequired()
            .HasColumnName("image")
            .HasMaxLength(200)
            .HasDefaultValueSql("('')");

        entity.Property(e => e.LName)
            .IsRequired()
            .HasColumnName("lName")
            .HasMaxLength(30);

        entity.Property(e => e.Province)
            .HasColumnName("province")
            .HasDefaultValueSql("((1))");
    });

    OnModelCreatingPartial(modelBuilder);
}

When scaffolding the database with the --data-annotations option, most meta data will be added using data annotations, but even here the following Fluent API calls get generated:

protected override void OnModelCreating(ModelBuilder modelBuilder)
{
    modelBuilder.Entity<Member>(entity =>
    {
        entity.Property(e => e.Education).HasDefaultValueSql("((1))");

        entity.Property(e => e.Image).HasDefaultValueSql("('')");

        entity.Property(e => e.Province).HasDefaultValueSql("((1))");
    });

    OnModelCreatingPartial(modelBuilder);
}

So the generated scripts are correct.

It is theoreticall possible to use the [DatabaseGenerated(DatabaseGeneratedOption.Identity)] data annotation to signal that the database will generate values by itself when adding an entity.

However, this would not preserve the information of what value this would be, because the [DatabaseGenerated] attribute does not have a property to specify a default value. Since you might want to use migrations after you scaffolded the database, the default value meta data might be quite useful.

By the way, there are no default value calls generated for the BirthDate and Gender properties, because their database defined DEFAULT constraint are the same as the CLR default value of those types (null for DateTime? and false for bool).


As a sidenote, I consider using [DatabaseGenerated] as confusing/misleading, because of its outdated option names. The Fluent API with its HasDefaultValue(), HasDefaultValueSql(), HasComputedColumnSql(), ValueGeneratedOnAdd() and ValueGeneratedOnAddOrUpdate() methods is quite expressive in comparison and should be used instead even in cases where not explicitly necessary.

Answered by lauxjpn on December 1, 2021

Add your own answers!

Ask a Question

Get help from others!

© 2024 TransWikia.com. All rights reserved. Sites we Love: PCI Database, UKBizDB, Menu Kuliner, Sharing RPP