EFCore HasDefaultValueSql

今天小伙伴在代码中遇到了有关 HasDefaultValue 的疑问,这里整理澄清下...

在使用 Entity Framework Core (EFCore) 配置实体时,HasDefaultValue 方法会为数据库列设置一个默认值。该默认值的行为取决于以下条件:


1. 配置 HasDefaultValue 的应用场景

HasDefaultValue 主要在以下场景中生效:

  • 首次创建表时:当迁移生成 CREATE TABLE 的 SQL 脚本时,会在列定义中附带默认值。
  • 列被新增到现有表时:在迁移中,新增列时,如果指定了 HasDefaultValue,生成的 SQL 脚本会为新增列设置默认值。

示例:

modelBuilder.Entity<MyEntity>() 
    .Property(e => e.MyColumn) 
    .HasDefaultValue(100); 

2. 默认值的应用条件

1) 创建表

如果使用迁移创建表,HasDefaultValue 会为列添加默认值。例如:

CREATE TABLE MyEntity ( 
    Id INT PRIMARY KEY, 
    MyColumn INT DEFAULT 100 
); 
2) 添加新列

如果表已经存在,且通过迁移为现有表新增列,HasDefaultValue 会生成如下 SQL:

ALTER TABLE MyEntity ADD MyColumn INT DEFAULT 100; 

在添加列时,DEFAULT 值会应用到已存在的行。

3) 插入数据

当应用程序通过 EFCore 插入记录,而未显式为列提供值时:

  • EFCore 会让数据库使用定义的默认值(依赖于数据库执行)。

注意:EFCore 不会在内存中自动填充默认值到实体属性上。


3. 特殊条件下的行为

1) 与 HasDefaultValueSql 的区别
  • HasDefaultValue:直接定义一个常量值。
  • HasDefaultValueSql:允许使用 SQL 表达式设置默认值。

例如:

modelBuilder.Entity<MyEntity>() 
    .Property(e => e.MyColumn) 
    .HasDefaultValueSql("GETDATE()"); 

生成的 SQL:

   ALTER TABLE MyEntity ADD MyColumn DATETIME DEFAULT GETDATE(); 
2) 更新表格时的影响

如果尝试将现有列的默认值修改为另一个值,EFCore 迁移中不会自动生成 ALTER COLUMN SQL,需要手动调整迁移。

3) 在内存中的作用

在运行时,HasDefaultValue 不会对未赋值的属性生效,即在 EFCore 中 HasDefaultValue 仅影响数据库的默认行为。


4. 实际示例与注意事项

代码示例
public class MyEntity 
{ 
    public int Id { get; set; } 
    public int MyColumn { get; set; } 
} 

// 配置 
modelBuilder
    .Entity<MyEntity>() 
    .Property(e => e.MyColumn) 
    .HasDefaultValue(100); 
生成的迁移代码
migrationBuilder.CreateTable( 
    name: "MyEntity",
    columns: table => new 
    { 
        Id = table.Column<int>(nullable: false) 
             .Annotation("SqlServer:Identity", "1, 1"), 
        MyColumn = table.Column<int>(nullable: false, defaultValue: 100) 
    }, 
    constraints: table => 
    { 
        table.PrimaryKey("PK_MyEntity", x => x.Id); 
    }); 
插入数据的行为
  • 如果你执行如下代码:
context.MyEntities.Add(new MyEntity { Id = 1 }); 
context.SaveChanges(); 

结果中 MyColumn 的值会由数据库设置为 100


5. 总结

HasDefaultValue 在以下情况下生效:

  1. 数据库表初次创建时。
  2. 为现有表新增列时。
  3. 插入数据时,如果 EFCore 没有为该列赋值,则数据库会自动使用默认值。

如果你想在代码中为未赋值的属性提供默认值,需额外在 C# 类中定义默认值逻辑。

在使用 Entity Framework Core 创建实体并保存到数据库时,如果你为属性赋值了,即使这个值与 HasDefaultValue 配置的值相同,EFCore 的行为取决于以下几个因素:

1. EFCore 的默认行为

  • 显式赋值的属性: 即使属性的值与 HasDefaultValue 中定义的值相同,EFCore 会将其视为已显式设置。因此,生成的 SQL 插入语句会包含该字段及其值。

示例:

modelBuilder.Entity<MyEntity>() 
    .Property(e => e.MyColumn) 
    .HasDefaultValue(100); 

var entity = new MyEntity 
{ 
    MyColumn = 100 // 显式赋值与默认值相同 
}; 

context.MyEntities.Add(entity);
context.SaveChanges(); 

生成的 SQL 类似如下:

INSERT INTO MyEntity (MyColumn) VALUES (100); 

2. 如何忽略字段

EFCore 只有在属性未显式赋值(即为 null 或默认类型值,如 0 对于整型)时,才会让数据库使用 HasDefaultValue 配置的默认值。

示例:

var entity = new MyEntity(); // 未赋值 
MyColumn context.MyEntities.Add(entity);
context.SaveChanges(); 

生成的 SQL 类似如下:

INSERT INTO MyEntity DEFAULT VALUES; 

如果表的 MyColumn 定义了默认值 100,那么数据库会将其设置为 100


3. 如何避免显式赋值时重复生成字段

如果你希望 EFCore 在插入数据时忽略与默认值相同的显式赋值字段,可以通过以下方式实现:

1) 使用默认值优化器

手动检测属性值是否等于默认值,并在这种情况下将其设置为 null

var entity = new MyEntity 
{ 
    MyColumn = 100 // 与默认值相同 
}; 

if (entity.MyColumn == 100) 
{ 
    entity.MyColumn = default; // 设置为默认值 
}

context.MyEntities.Add(entity); 
context.SaveChanges(); 

生成的 SQL:

INSERT INTO MyEntity DEFAULT VALUES; 
2) 自定义 SaveChanges 拦截器

DbContext.SaveChanges 方法中拦截并移除与默认值相同的字段:

public override int SaveChanges() 
{ 
    foreach (var entry in ChangeTracker.Entries<MyEntity>()) 
    { 
        if (entry.State == EntityState.Added && entry.Entity.MyColumn == 100) 
        {
            entry.Property(e => e.MyColumn).IsModified = false; 
        } 
    } 

    return base.SaveChanges(); 
} 

4. 总结

  1. 如果为属性显式赋值,即使值与 HasDefaultValue 一样,EFCore 会生成包含该字段的 SQL。
  2. 要避免生成重复字段,可以在代码逻辑中手动移除默认值的赋值,或使用自定义拦截器动态处理。
  3. 默认值 (HasDefaultValue) 仅在未赋值或未提供字段时,由数据库自动填充。

补充:

配置字段为数据库生成

protected override void OnModelCreating(ModelBuilder modelBuilder) 
{ 
    modelBuilder.Entity<Example>() 
    .Property(e => e.Age) 
    .HasDefaultValueSql("18");} 

归纳一下:

  1. HasDefaultValueSql("18") 的作用:

    • 它的主要作用是 在模型构建时告诉 EF Core 该字段在数据库中有默认值
    • EF Core 不会强制使用 HasDefaultValueSql 配置的值生成 INSERT 语句,而是让数据库的默认值(DEFAULT 定义)生效。
  2. EF Core 生成 INSERT 的行为:

    • 如果字段没有显式赋值(即在代码中未为该字段赋值),EF Core 不会在生成的 INSERT 语句中包含该字段,从而依赖数据库在 SCHEMA 上的 DEFAULT 值。
    • 如果代码中显式赋值了该字段,即使值与 HasDefaultValueSql 的配置一致,EF Core 仍会在 INSERT 语句中包含该字段,并使用显式赋值的值。
  3. 实际生效的值:

    • 关键是数据库表定义中的 DEFAULT 值(由 CREATE TABLEALTER TABLE 设置)。
    • HasDefaultValueSql 中配置的 SQL 只是 帮助 EF Core 在迁移中设置数据库表的默认值,一旦表的 SCHEMA 定义了默认值,EF Core 就不再干涉。
  4. HasDefaultValueSql 的核心意义:

    • 它是在 数据库迁移时,帮助生成类似如下的 SQL:
      ALTER TABLE Example ADD CONSTRAINT DF_Age DEFAULT 18 FOR Age; 
    • 一旦表的默认值设置完成,EF Core 的 HasDefaultValueSql 配置就不再直接影响运行时行为

示例验证

表定义
CREATE TABLE Example ( Id INT PRIMARY KEY, Name NVARCHAR(50), Age INT DEFAULT 18 ); 
Fluent API 配置
protected override void OnModelCreating(ModelBuilder modelBuilder) 
{
    modelBuilder.Entity<Example>() 
    .Property(e => e.Age) 
    .HasDefaultValueSql("18"); 
} 
插入代码
var example = new Example 
{ 
     Name = "Alice" // Age 未赋值 }; 
     context.Examples.Add(example);
     context.SaveChanges();  
}

生成的 SQL:

INSERT INTO Example (Name) VALUES ('Alice'); -- Age 列未包含 

数据库最终插入:

Id | Name | Age 1 | Alice | 18 
如果数据库默认值改变

假如数据库表的 DEFAULT 定义改为 20,代码和 Fluent API 不变:

生成的 SQL 仍然是:

INSERT INTO Example (Name) VALUES ('Alice'); -- Age 列未包含 

但最终插入的值会变为:

Id | Name | Age 1 | Alice | 20 

这说明 运行时实际生效的是数据库表的 DEFAULT


总结

  • HasDefaultValueSql 的配置值不会直接影响运行时行为,其作用主要是用于迁移时生成表的默认值定义。
  • 最终起作用的是数据库表的默认值,而不是 HasDefaultValueSql 配置中的值。
  • 只要字段未显式赋值,无论是可空还是非可空,EF Core 都会依赖数据库表的默认值生效。



本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/953277.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

【2025最新】100%通过的计算机毕设新题目

五个类别的计算机毕业设计题目10个&#xff0c;需要更多新鲜题目请私信博主。 类别一&#xff1a;人工智能与机器学习 题目1&#xff1a;基于深度学习的图像识别系统 内容解释&#xff1a;开发一个使用深度学习技术的图像识别系统&#xff0c;能够识别并分类各种物体、场景…

[DO374] Ansible 配置文件

[DO374] Ansible 配置文件 1. 配置文件位置2. 配置文件3. Ansible 配置4. Ansible的Ad-hoc5. Ansible 模块6. playbook段落7. 任务执行后续8. Ansible 变量8.1 ansible 变量的定义8.1.1 主机变量8.1.2 主机组变量 8.2 vars的循环 9. Ansible Collection10. Ansible-galaxy 安装…

CMake构建C#工程(protobuf)

工程目录结构 第一级CMakeLists.txt cmake_minimum_required(VERSION 3.0.0) # 指定为csharp工程 project(CSharpDemo CSharp) # 添加二级目录 add_subdirectory(src) 第二级CMakeLists.txt cmake_minimum_required(VERSION 3.0.0) project(CSharpDemo CSharp)# 指定protoc…

全栈面试(一)Basic/微服务

文章目录 项目地址一、Basic InterviewQuestions1. tell me about yourself?2. tell me about a time when you had to solve a complex code problem?3. tell me a situation that you persuade someone at work?4. tell me a about a confict with a teammate and how you…

专题 - STM32

基础 基础知识 STM所有产品线&#xff08;列举型号&#xff09;&#xff1a; STM产品的3内核架构&#xff08;列举ARM芯片架构&#xff09;&#xff1a; STM32的3开发方式&#xff1a; STM32的5开发工具和套件&#xff1a; 若要在电脑上直接硬件级调试STM32设备&#xff0c;则…

容器技术全面攻略:Docker的硬核玩法

文章背景 想象一下&#xff0c;一个项目终于要上线了&#xff0c;结果因为环境配置不一致&#xff0c;测试服务器一切正常&#xff0c;生产环境却宕机了。这是开发者噩梦的开始&#xff0c;也是Docker救世主角色的登场&#xff01;Docker的出现颠覆了传统环境配置的方式&#…

【论文阅读】Workload Dependent Performance Evaluation of the Linux 2.6 I/O Schedulers

文章目录 某些背景知识的科普&#xff08;依赖GPT&#xff09;GPT简短总结摘要-Abstract引言-Introduction1 I/O Scheduling and the BIO LayerThe 2.6 Deadline I/O Scheduler2.1 The 2.6 Anticipatory I/O scheduler2.2 The 2.6 CFQ Scheduler2.3 The 2.6 noop I/O scheduler…

LLMBook 中 数据集下载地址整理收集

本文针对《LLMBook》大语言模型 | LLMBook-zh 中的42个数据集进行完整下载地址整理收集。 具体整理部分关于第三章 大型语言模型资源 1、常用预训练24个数据集下载地址整理收集 2、指令微调18个数据集下载地址整理收集 3、人类对齐8个数据集下载地址整理收集 《大语言模型》…

http和https有哪些不同

http和https有哪些不同 1.数据传输的安全性&#xff1a;http非加密&#xff0c;https加密 2.端口号&#xff1a;http默认80端口&#xff0c;https默认443端口 3.性能&#xff1a;http基于tcp三次握手建立连接&#xff0c;https在tcp三次握手后还有TLS协议的四次握手确认加密…

LabVIEW滤波器功能

程序通过LabVIEW生成一个带噪声的正弦波信号&#xff0c;并利用滤波器对其进行信号提取。具体来说&#xff0c;它生成一个正弦波信号&#xff0c;叠加高频噪声后形成带噪信号&#xff0c;再通过低通滤波器滤除噪声&#xff0c;提取原始正弦波信号。整个过程展示了信号生成、噪声…

基于华为atlas的重车(满载)空车(空载)识别

该教程主要是想摸索出华为atlas的基于ACL的推理模式。最终实现通过煤矿磅道上方的摄像头&#xff0c;识别出车辆的重车&#xff08;满载&#xff09;、空车&#xff08;空载&#xff09;情况。本质上是一个简单的检测问题。 但是整体探索过程比较坎坷&#xff0c;Tianxiaomo的…

pytest+allure 入门

使用allure如何生成自动化测试报​​​​​​告 &#xff1f;一文详解allure的使用 。_allure测试报告-CSDN博客 例子&#xff1a; import allure import pytest import osallure.epic("闹钟") allure.feature("闹钟增删") class TestSchedule():def setu…

excel VBA 基础教程

这里写目录标题 快捷键选择所有有内容的地方 调试VBA录制宏&#xff0c;打开VBA开发工具录制宏,相当于excel自动写代码&#xff08;两个表格内容完全一致才可以&#xff09; 查看宏代码保持含有宏程序的文件xlsm后缀&#xff08;注意很容易有病毒&#xff09;宏文件安全设置 使…

Excel数据叠加生成新DataFrame:操作指南与案例

目录 一、准备工作 二、读取Excel文件 三、数据叠加 四、处理重复数据&#xff08;可选&#xff09; 五、保存新DataFrame到Excel文件 六、案例演示 七、注意事项 八、总结 在日常数据处理工作中&#xff0c;我们经常需要将不同Excel文档中的数据整合到一个新的DataFra…

Django创建数据表、模型、ORM操作

1、创建项目 django-admin startproject PersonInfosProject 2、创建项目应用&#xff0c;进入PersonInfosProject文件夹&#xff0c;新建index应用&#xff0c;使用命令 cd PersonInfosProject python manage.py startapp 新建完成之后的目录结构 3、新建数据模型&#xf…

ZYNQ初识10(zynq_7010)UART通信实验

基于bi站正点原子讲解视频&#xff1a; 系统框图&#xff08;基于串口的数据回环&#xff09;如下&#xff1a; 以下&#xff0c;是串口接收端的波形图&#xff0c;系统时钟和波特率时钟不同&#xff0c;为异步时钟&#xff0c;&#xff0c;需要先延时两拍&#xff0c;将时钟同…

【ORACLE战报】2025.1月OCP | MySQL考试

2025.1月【最新考试成绩出炉】 OCP战报 MySQL 战报 部分学员成绩及证书

力扣经典练习题之198.打家劫舍

今天继续给大家分享一道力扣的做题心得今天这道题目是198.打家劫舍,这是一道非常经典的问题,在动态规划中经常考到这类问题,题目如下: 题目链接:198.打家劫舍 1,题目分析 首先此题就是给我们了一个数组,代表可以偷的房屋中的对应的金额,我们是一个小偷,一次可以偷很多…

【数据库】一、数据库系统概述

文章目录 一、数据库系统概述1 基本概念2 现实世界的信息化过程3 数据库系统内部体系结构4 数据库系统外部体系结构5 数据管理方式 一、数据库系统概述 1 基本概念 数据&#xff1a;描述事物的符号记录 数据库&#xff08;DB&#xff09;&#xff1a;长期存储在计算机内的、…

Redis有哪些常用应用场景?

大家好&#xff0c;我是锋哥。今天分享关于【Redis有哪些常用应用场景&#xff1f;】面试题。希望对大家有帮助&#xff1b; Redis有哪些常用应用场景&#xff1f; 1000道 互联网大厂Java工程师 精选面试题-Java资源分享网 Redis 是一个高性能的开源键值对&#xff08;Key-Va…