序列化 JSON 时崩了?99% 是 EF 延迟加载惹的祸,三种解法拿走不谢
一、先看一个“翻车”现场假设我们有这么三层数据主表fin_voucher_rule_master凭证规则明细表fin_voucher_rule_detail规则明细条件表fin_voucher_rule_condition明细下的条件关系很简单一个主表有多个明细一个明细有多个条件。DAL 层数据访问层代码public static Listfin_voucher_rule_master GetFin_Voucher_Rule_Masters(string name) { using (var db new PcbEntities()) { var q db.fin_voucher_rule_master.AsNoTracking(); if (!string.IsNullOrEmpty(name)) q q.Where(x x.business_type.Contains(name)); return q.ToList(); } }服务层代码转成 JSON 返回给前端public static string GetFin_Voucher_Rule_Masters(string name) { var list DAL.VoucherRuleMasterDAL.GetFin_Voucher_Rule_Masters(name); string json ZhPcb.Common._Json.GetJsonfin_voucher_rule_master(list); json {\total\: list.Count ,\rows\: json }; return json; }看着没啥问题吧结果一跑崩了System.ObjectDisposedException: 此 ObjectContext 实例已释放不可再用于需要连接的操作。刚子第一次遇到的时候也是一脸懵我明明ToList()了数据都查出来了怎么还说“上下文已释放”二、原因分析都是“延迟加载”惹的祸啥是延迟加载简单说EF 默认开启了一个“懒汉模式”你查主表的时候它只把主表自己的字段比如 Id、Name给你。至于主表关联的明细fin_voucher_rule_detail它先不查等你真正用到的时候它再偷偷去数据库查。这个“偷偷查”的动作就叫延迟加载。为啥ToList()之后还会查数据库很多人以为ToList()就万事大吉了数据全在内存里了。错ToList()只加载了你明确查询的那些字段。你没有Include的导航属性EF 不会主动加载。等你一访问它比如 JSON 序列化器想把它转成字符串EF 才反应过来“哎呀这个还没查呢我赶紧去数据库拿。”——结果发现DbContext已经在using外面被释放了于是报错。本案例的执行流程拆解版DAL 层using (var db new PcbEntities())创建数据库连接。执行.AsNoTracking().Where(...).ToList()只加载了主表自身的字段。using块结束db被释放连接关闭。服务层调用 JSON 序列化工具。序列化器很“勤奋”它会递归遍历master对象的所有属性包括导航属性比如fin_voucher_rule_detail。当序列化器访问master.fin_voucher_rule_detail时EF 的代理对象尝试延迟加载——但DbContext已经没了于是抛出ObjectDisposedException。划重点你让 EF 帮你查主表它只给了你主表。你以为完事了结果序列化的时候非要去看明细EF 说“那我再去数据库拿”可数据库连接早就关了。不崩你崩谁三、解决方案三种按需选方案一关掉延迟加载最简单在DbContext里把延迟加载功能关掉。这样 EF 就不会“偷偷”查数据库了访问导航属性只会得到null或空集合不会报错。using (var db new PcbEntities()) { db.Configuration.LazyLoadingEnabled false; // EF6 写法 // 如果是 EF Coredb.ChangeTracker.LazyLoadingEnabled false; var q db.fin_voucher_rule_master.AsNoTracking(); // ... return q.ToList(); }优点改一行代码搞定省心。缺点如果业务上确实需要明细数据你得自己Include。划重点Web 应用一般推荐全局关掉延迟加载然后在需要的地方手动Include。这样最可控。方案二提前加载导航属性Eager Loading用Include和ThenInclude告诉 EF“把明细和条件也一起查出来别偷懒。”EF Core 写法推荐using Microsoft.EntityFrameworkCore; public static Listfin_voucher_rule_master GetFin_Voucher_Rule_Masters(string name) { using (var db new PcbEntities()) { var q db.fin_voucher_rule_master .Include(m m.fin_voucher_rule_detail) .ThenInclude(d d.fin_voucher_rule_condition) .AsNoTracking(); if (!string.IsNullOrEmpty(name)) q q.Where(x x.business_type.Contains(name)); return q.ToList(); } }EF6 写法不支持ThenInclude用字符串或Selectusing System.Data.Entity; public static Listfin_voucher_rule_master GetFin_Voucher_Rule_Masters(string name) { using (var db new PcbEntities()) { var q db.fin_voucher_rule_master .Include(fin_voucher_rule_detail.fin_voucher_rule_condition) .AsNoTracking(); // 或者用 lambda.Include(x x.fin_voucher_rule_detail.Select(d d.fin_voucher_rule_condition)) if (!string.IsNullOrEmpty(name)) q q.Where(x x.business_type.Contains(name)); return q.ToList(); } }优点一次查询把所有需要的数据都拿到性能好。缺点得提前知道要加载哪些导航属性。划重点Include就是“带上明细”ThenInclude就是“再带上明细下面的条件”。EF Core 的写法更直观EF6 稍微别扭点但也能用。方案三用 DTO 投影最专业不直接返回实体而是建一个数据传输对象DTO只放你需要返回的字段。查询的时候直接投影彻底绕过导航属性。public class VoucherRuleMasterDto { public int Id { get; set; } public string BusinessType { get; set; } public ListVoucherRuleDetailDto Details { get; set; } } public static ListVoucherRuleMasterDto GetVoucherRuleMasters(string name) { using (var db new PcbEntities()) { var query db.fin_voucher_rule_master.AsNoTracking(); if (!string.IsNullOrEmpty(name)) query query.Where(x x.business_type.Contains(name)); return query.Select(m new VoucherRuleMasterDto { Id m.Id, BusinessType m.business_type, Details m.fin_voucher_rule_detail.Select(d new VoucherRuleDetailDto { Id d.Id, Condition d.fin_voucher_rule_condition.Description }).ToList() }).ToList(); } }优点只返回前端真正需要的数据网络传输量小。彻底解耦数据库模型和 API 接口。再也不用担心延迟加载和序列化问题。缺点多写几个 DTO 类可以用 AutoMapper 偷懒。划重点DTO 方案是最“正统”的做法推荐在正式项目里用。实体是给数据库用的DTO 是给前端用的别混在一起。四、EF6 和 EF Core 的 Include/ThenInclude 区别一张表看懂很多从 EF6 转到 EF Core 的兄弟会被ThenInclude搞晕。刚子给你总结一下你要加载什么EF6 写法EF Core 写法单个导航属性如 Detail.Include(x x.Detail)或Include(Detail).Include(x x.Detail)嵌套属性Detail.Condition.Include(x x.Detail.Condition)或Include(Detail.Condition).Include(x x.Detail).ThenInclude(d d.Condition)集合的嵌套属性Details里的Condition.Include(x x.Details.Select(d d.Condition)).Include(x x.Details).ThenInclude(d d.Condition)常见坑编译错误Include does not contain a definition for ThenInclude→ 说明你用的是 EF6别用ThenInclude。运行时InvalidOperationException: A second operation started on this context before a previous operation completed→ 你在遍历结果时又触发了延迟加载关掉它或者提前Include。五、最佳实践总结照着做不踩坑Web 应用全局关闭延迟加载在DbContext构造函数里加上public PcbEntities() { this.Configuration.LazyLoadingEnabled false; // EF6 // 或 this.ChangeTracker.LazyLoadingEnabled false; // EF Core }需要关联数据的地方手动Include。只读查询一律用AsNoTracking()提升性能减少内存占用。别在using块外面访问导航属性要么提前Include要么把序列化操作放在using里面。优先用 DTO 投影这是最干净、最专业的做法。搞清楚你的 EF 版本看packages.config或.csprojEntityFramework6.x → EF6Microsoft.EntityFrameworkCore→ EF Core六、完整示例拿来即用以下是一个兼容 EF6 和 EF Core 的写法通过条件编译public static Listfin_voucher_rule_master GetFin_Voucher_Rule_Masters(string name) { using (var db new PcbEntities()) { // 关闭延迟加载 db.Configuration.LazyLoadingEnabled false; var q db.fin_voucher_rule_master.AsNoTracking(); // 预先加载三层数据 #if EF6 q q.Include(fin_voucher_rule_detail.fin_voucher_rule_condition); #else q q.Include(m m.fin_voucher_rule_detail) .ThenInclude(d d.fin_voucher_rule_condition); #endif if (!string.IsNullOrEmpty(name)) q q.Where(x x.business_type.Contains(name)); return q.ToList(); } }最后刚子想说ObjectDisposedException这个错基本每个用 EF 的人都遇到过。搞懂了延迟加载的原理解决起来其实很简单。记住一句话在 DbContext 还活着的时候把你需要的数据全都显式加载好。如果你觉得这篇文章帮你搞明白了点个赞、转给还在被 EF 坑的兄弟。

相关新闻

先腾Stats:数据驱动制造,国产统计分析的新选择

先腾Stats:数据驱动制造,国产统计分析的新选择

在现代制造业与科研领域,数据统计分析软件已成为企业提升质量管理水平、优化生产流程、支撑科学决策不可或缺的基础工具。从生产过程中的质量波动监控,到研发阶段的工艺参数验证,再到多维度数据的深度挖掘,统计分析软件贯穿了企业…

2026/7/18 22:08:50阅读更多 →
【AI专栏】图解深度学习-AI infra工程师必知必会 - 第 04 章:训练 vs 推理

【AI专栏】图解深度学习-AI infra工程师必知必会 - 第 04 章:训练 vs 推理

博主介绍:程序喵大人 35 - 资深C/C/Rust/Android/iOS客户端开发10年大厂工作经验嵌入式/人工智能/自动驾驶/音视频/游戏开发入门级选手《C20高级编程》《C23高级编程》等多本书籍著译者更多原创精品文章,首发gzh,见文末👇&#x…

2026/7/18 22:08:50阅读更多 →
园区VOCs集群治理工程实践|越华环保集团绿岛RTO系统设计与落地分析

园区VOCs集群治理工程实践|越华环保集团绿岛RTO系统设计与落地分析

越华环保集团针对园区VOCs集群治理工况痛点,完成绿岛RTO系统工程落地,通过系统化工艺设计、节能结构优化、智能自控升级,解决分散治理低效、高能耗、达标不稳等工程难题。 1、集群VOCs治理的核心工程痛点 在工业环保工程落地中,产…

2026/7/18 22:08:50阅读更多 →
大模型想要稳定应用,离不开训练与推理两套算力体系

大模型想要稳定应用,离不开训练与推理两套算力体系

生成式 AI 掀起新一轮数字产业变革,智能算力从前沿概念转变为实体经济刚需。纵观整个 AI 算力产业链,两大趋势清晰可见:一是高密度智算集群持续规模化建设;二是算力商业模式持续迭代,Token标准化服务快速普及&#xff…

2026/7/18 23:45:03阅读更多 →
大家好,我是UWA GPM「小Q」,今天是我加入项目的第一天

大家好,我是UWA GPM「小Q」,今天是我加入项目的第一天

大家好,我是 UWA GPM 小Q,今天正式到岗! 各位游戏研发的小伙伴们,大家好~ 我是今天刚入职的新同事小Q,你的AI质量经理。 按新人的规矩,先交代三个“不”:我不占工位,不…

2026/7/18 23:45:03阅读更多 →
快手视频下载神器KS-Downloader:三步搞定无水印高清下载

快手视频下载神器KS-Downloader:三步搞定无水印高清下载

快手视频下载神器KS-Downloader:三步搞定无水印高清下载 【免费下载链接】KS-Downloader 快手(KuaiShou)作品视频/图片下载工具 项目地址: https://gitcode.com/gh_mirrors/ks/KS-Downloader 还在为无法保存喜欢的快手视频而烦恼吗&am…

2026/7/18 23:45:03阅读更多 →
如何创建吸引流量的运动商城网站?

如何创建吸引流量的运动商城网站?

当下运动消费市场持续升温,运动装备、健身器材、运动周边、场馆耗材等产品需求稳步上涨。很多运动实体店、体育商户、场馆经营者,都想搭建专属运动商城网站,打通线上销售渠道。但多数自建商城存在流量少、曝光低、转化差、功能杂乱等问题&…

2026/7/18 23:45:03阅读更多 →
瑞德克斯的页面秩序感有没有条理?

瑞德克斯的页面秩序感有没有条理?

把页面秩序感有没有条理放进真实使用情境里观察,瑞德克斯是否重视基础感受就会更清楚。像调整账户信息设置这种步骤,最能体现平台是否把安全提醒和操作说明安排得稳妥。这些细节拼在一起,才构成瑞德克斯比较自然、也比较稳健的整体印象。从另…

2026/7/18 23:45:03阅读更多 →
记录一次种牙:半年后的真实感受

记录一次种牙:半年后的真实感受

种完牙半年了,记录一下感受。种之前缺了一颗牙好几年,一直拖着。主要是怕疼、怕花钱、怕折腾。后来旁边的牙开始歪了,才下定决心。种之后最大的变化是吃饭方便了。以前缺牙的地方不敢嚼,现在两边都能正常用。恢复比想象中快&#…

2026/7/18 23:43:03阅读更多 →
VSCode TypeScript 环境配置对比:全局安装 vs 项目本地安装的4个关键差异

VSCode TypeScript 环境配置对比:全局安装 vs 项目本地安装的4个关键差异

VSCode TypeScript 环境配置对比:全局安装 vs 项目本地安装的4个关键差异当你在VSCode中启动一个新的TypeScript项目时,第一个技术决策往往从安装方式开始。这个看似简单的选择——全局安装还是项目本地安装——实际上会深刻影响你的开发流程、团队协作和…

2026/7/18 10:49:13阅读更多 →
智慧树刷课插件:5分钟实现自动化学习的智能助手

智慧树刷课插件:5分钟实现自动化学习的智能助手

智慧树刷课插件:5分钟实现自动化学习的智能助手 【免费下载链接】zhihuishu 智慧树刷课插件,自动播放下一集、1.5倍速度、无声 项目地址: https://gitcode.com/gh_mirrors/zh/zhihuishu 智慧树刷课插件是一款专为智慧树在线教育平台设计的Chrome浏…

2026/7/18 8:49:08阅读更多 →
Steam创意工坊下载器WorkshopDL:跨平台游戏模组获取的终极解决方案

Steam创意工坊下载器WorkshopDL:跨平台游戏模组获取的终极解决方案

Steam创意工坊下载器WorkshopDL:跨平台游戏模组获取的终极解决方案 【免费下载链接】WorkshopDL WorkshopDL - The Best Steam Workshop Downloader 项目地址: https://gitcode.com/gh_mirrors/wo/WorkshopDL 你是否在GOG或Epic Games Store购买了心仪的游戏…

2026/7/18 14:49:24阅读更多 →
从模糊意图到可执行指令:Claude PRD中Prompt Engineering与需求颗粒度的5级映射法则

从模糊意图到可执行指令:Claude PRD中Prompt Engineering与需求颗粒度的5级映射法则

更多请点击: https://kaifayun.com 第一章:从模糊意图到可执行指令:Claude PRD中Prompt Engineering与需求颗粒度的5级映射法则 在Claude驱动的产品需求文档(PRD)生成实践中,原始业务意图往往以自然语言片…

2026/7/18 0:00:14阅读更多 →
Cursor配置生成失效?3大隐藏陷阱+4行修复代码,资深工程师连夜整理的紧急补救清单

Cursor配置生成失效?3大隐藏陷阱+4行修复代码,资深工程师连夜整理的紧急补救清单

更多请点击: https://codechina.net 第一章:Cursor配置生成失效?3大隐藏陷阱4行修复代码,资深工程师连夜整理的紧急补救清单 Cursor 配置生成突然失效,是近期高频报障场景。表面看是 cursor.config.json 未更新或 LSP…

2026/7/18 0:00:14阅读更多 →
某智驾大牛创业

某智驾大牛创业

作者:钟声编辑:Mark出品:红色星际头图:智能驾驶图片据悉,国内某头部智驾公司端到端模型技术大牛Z投身创业,并且已经拿到融资。Z不仅是该头部公司内部最年轻的对标阿里P10级别技术负责⼈,更是业内…

2026/7/18 0:00:14阅读更多 →
YOLOv8推理性能优化:从1.2FPS到35FPS的全链路加速实践

YOLOv8推理性能优化:从1.2FPS到35FPS的全链路加速实践

如果你在部署 YOLOv8 时,发现推理速度只有可怜的 1-2 FPS,而别人的演示视频却能跑到 30 FPS 以上,那么问题很可能不在模型本身,而在于你的整个处理链路。很多开发者拿到一个训练好的 YOLOv8 模型后,会直接使用官方示例…

2026/7/18 22:49:46阅读更多 →
Coze与Dify对比指南:低代码AI应用开发从入门到实战

Coze与Dify对比指南:低代码AI应用开发从入门到实战

1. 从零到一:为什么你需要了解 Coze 和 Dify?如果你对 AI 应用开发感兴趣,但一看到“大模型”、“智能体”、“工作流”这些词就头疼,觉得门槛太高,那这篇文章就是为你准备的。很多开发者,包括我自己&#…

2026/7/18 14:49:24阅读更多 →
AI生图工具怎么选?2026年6月版实测对比

AI生图工具怎么选?2026年6月版实测对比

做自媒体的朋友应该都有体会:配图一直是个让人头疼的问题。2026年,AI生图工具已经非常成熟了,但工具太多反而不知道怎么选。以下是截至2026年6月我对主流AI生图工具的实测对比。Midjourney V8.1:速度之王2026年6月11日&#xff0c…

2026/7/18 18:49:35阅读更多 →