当前位置: 首页 > news >正文

EF Core 深入学习

EF Core操作实体属性的内部机制

  • 核心概念: EF Core 的直接字段访问

  • EF Core 在操作实体属性时,会尽量绕过属性的 getter/setter,直接操作背后的私有字段

    • 为什么要这么做?基于性能和对特殊功能支持的考虑
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;namespace ConsoleApp1
{public class Person{public long Id { get; set; }// public string Name { get; set; } // 不用简写形式,更能验证结论private string _name; // 按照结论,会直接读_name,而不会先执行Name的get和set的逻辑public string Name{get {Console.WriteLine("get被调用了!");return _name;}set {Console.WriteLine("set被调用了!");_name = value;}}}
}
  • 数据库配置和主程序代码如下
// MyDbContext.cs
using Microsoft.EntityFrameworkCore;
namespace ConsoleApp1
{public class MyDbContext : DbContext{public DbSet<Person> Persons { get; set; }protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder){base.OnConfiguring(optionsBuilder);// 添加 TrustServerCertificate=true 解决证书问题optionsBuilder.UseSqlServer("Server=.;Database=ddd1;Trusted_Connection=True;TrustServerCertificate=true;");}}
}// Program.cs
using ConsoleApp1;Person p1 = new();
p1.Name = "yzk"; // 这里调用 setter,输出 "set被调用了!"
using var ctx = new MyDbContext();
ctx.Persons.Add(p1);
ctx.SaveChanges(); // 这里应该调用 getter,但实际没有!
  • 本次程序的运行结果
set被调用了!
  • 按照预想的结果,当执行完ctx.SaveChanges()后,控制台应该会打印get被调用了,然而并没有发生
    • 原因: EF Core 在保存时直接读取 _name 字段,没有通过 Name 属性的 getter。
using ConsoleApp1;//Person p1 = new();
//p1.Name = "yzk";
//using var ctx = new MyDbContext();
//ctx.Persons.Add(p1);
//ctx.SaveChanges();using var ctx = new MyDbContext();
Person p1 = ctx.Persons.First();
Console.WriteLine(p1.Id);
Console.WriteLine(p1.Name);  // 这里调用 getter
  • 程序运行结果
1
get被调用了!
yzk
  • 按理说,执行了两次Console,那么应该调用两次get,而事实上只调用了一次!
    • EF Core 在创建对象时直接设置 _name 字段,没有通过 setter
    • 只有当我们显式访问 p1.Name 时才调用 getter
  • 再次实验,当把字段从 _name 改为 xiaoming 后(主程序不变)
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;namespace ConsoleApp1
{public class Person{public long Id { get; set; }private string xiaoming;public string Name{get {Console.WriteLine("get被调用了!");return xiaoming;}set {Console.WriteLine("set被调用了!");xiaoming = value;}}}
}
  • 运行结果如下
set被调用了!      // 创建对象时通过 setter
get被调用了!      // EF Core 内部跟踪时调用 getter  
get被调用了!      // 再次内部调用
1
get被调用了!      // 我们显式访问时调用
yzk

原理分析

EF Core 的字段发现规则

EF Core 按照以下顺序寻找匹配的字段:

  1. _<propertyName>(如 _name
  2. _<PropertyName>(如 _Name
  3. <propertyName>(如 name
  4. <PropertyName>(如 Name

为什么会这样设计?

  1. 性能优化:直接访问字段比通过属性访问器更快
  2. 绕过业务逻辑:避免属性 setter 中的验证逻辑影响数据加载
  3. 跟踪变化:EF Core 需要直接监控字段值的变化

需要避免的情况

public string Name
{get { return _name; }set { if(string.IsNullOrEmpty(value))throw new Exception("名称不能为空"); // EF Core 加载数据时会触发异常!_name = value; }
}

推荐的实践

// 如果需要在 setter 中添加逻辑,要确保不影响 EF Core 的数据加载
public string Name
{get { return _name; }set { // 避免在这里添加严格的验证逻辑_name = value; // 或者添加不阻碍数据加载的逻辑}
}

总结

  • 数据加载时:EF Core 尽量直接操作字段,不触发属性逻辑
  • 显式访问时:才会调用我们定义的 getter/setter
  • 字段命名:会影响 EF Core 的行为方式

意义: 理解这个机制对于编写正确的 EF Core 实体类和避免潜在的 bug 非常重要!

http://www.jsqmd.com/news/52718/

相关文章:

  • Unit 4 Intensive Listening 2
  • 深入解析:51单片机基础-IO扩展(并转串 74HC165)
  • 实用指南:如何在 React 中实现键盘快捷键管理器以提升用户体验
  • 2025年十大GEO源头厂家口碑排行榜,南方网通GEO源头厂
  • 无线讲解器品牌TOP5权威推荐:哪个品牌适合导游使用、耐用性
  • 2025年五大靠谱纸桶包装设备制造商推荐,专业纸桶包装设备厂
  • .Net中WebApiController如何实现多版本兼容?
  • 2025年在线客服系统深度评测:五款主流产品全方位对比
  • 写题-2025.11
  • 修正开源控件kcontrols不能在linux使用中文输入法的bug
  • 【转载】Qt 路径中常用字符“./”、“../”、“/”、“*”的含义
  • 完整教程:掌握3D手部关键点检测:PyTorch深度学习实战
  • 2025年中国AI智能办公鼠标十大品牌推荐:鸿容AI智能办公
  • Git 安装流程
  • 2025安全环保充电器外壳厂家TOP5权威推荐:环保认证US
  • 【转载】Qt 断言Q_ASSERT的使用
  • 2025年修补防水涂料推荐厂家及其市场分析
  • 连续状态方程Tustin离散化处理 - 实践
  • 2025年北京、上海、深圳协议离婚律师推荐排行榜:哪个好?哪个靠谱?选哪个?
  • Shell脚本实战:15个提高工作效率的自动化脚本
  • 【转载】Qt 多次connect的坑
  • 2025年检查井定制厂家十大推荐,雨水检查井与预制装配式检查
  • 2025年襄阳地区十大包装盒定制企业推荐:知名的包装盒机构有
  • 2025年深圳东莞惠州塑胶外壳定制公司推荐:安全环保的塑胶外
  • 2025年修补料砂浆源头厂家对比榜
  • 2025年十大靠谱塑胶外壳厂家推荐,口碑靠谱的塑胶外壳供应商
  • 大模型高效微调(Finetune)实战教程
  • 【转载】Qt QCustomPlot 使用整理
  • Windows实用小工具使用教程!OFGB专治 Windows 11 广告的神器+自动滚屏小工具!
  • 八数码难题