0

我正在使用 EF Core 3.1 和使用 Linq-to-Entities 的数据库优先方法。但是当我用这段代码创建我的模型时

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

它不会[DatabaseGenerated(DatabaseGeneratedOption.Computed)]在具有默认值的生成的类属性上添加正确的值。

这是我的表脚本:

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
4

1 回答 1

0

搭建数据库时(不带该--data-annotations选项),会生成以下 Fluent API 调用,包括相应的.HasDefaultValueSql()调用:

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

当使用该--data-annotations选项构建数据库时,大多数元数据将使用数据注释添加,但即使在这里也会生成以下 Fluent API 调用:

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

所以生成的脚本是正确的。

理论上可以使用[DatabaseGenerated(DatabaseGeneratedOption.Identity)]数据注释来表示数据库在添加实体时将自行生成值。

但是,这不会保留这将是什么值的信息,因为该[DatabaseGenerated]属性没有指定默认值的属性。由于您可能希望在搭建数据库后使用迁移,因此默认值元数据可能非常有用。

顺便说一句,没有为BirthDateandGender属性生成默认值调用,因为它们的数据库定义的约束与这些类型( for和for )DEFAULT的 CLR 默认值相同。nullDateTime?falsebool


作为旁注,我认为使用[DatabaseGenerated]它会造成混淆/误导,因为它的选项名称已过时。相比之下,带有HasDefaultValue()HasDefaultValueSql()、和方法的 Fluent API 具有很强的表现力,即使在没有明确必要的情况下也应该使用它。HasComputedColumnSql()ValueGeneratedOnAdd()ValueGeneratedOnAddOrUpdate()

于 2020-07-22T22:13:52.777 回答