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
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
Get help from others!
Recent Answers
Recent Questions
© 2024 TransWikia.com. All rights reserved. Sites we Love: PCI Database, UKBizDB, Menu Kuliner, Sharing RPP