C# 实体框架 - 优化/最佳实践

     2023-04-12     271

关键词:

【中文标题】C# 实体框架 - 优化/最佳实践【英文标题】:C# Entity Framework - Optimization/Best Practices 【发布时间】:2021-04-30 13:34:19 【问题描述】:

我有一个具有以下结构的实体框架数据库:

“Lots”是零件的命名集合

“部件”是单独的部件

“站”是零件的结果

“工具”是站的结果

“测量”是工具的结果

对于一个给定的批次,大约。 53,000 个零件,在我的测试用例中有 6 个关联行,总行数为 318,001(很多 + 1)

我的问题是如何通过这种类型的数据关联来提高 Entity Framework 的性能。

删除批次(使用 MySQL 的 CASCADE 删除)大约需要。 12 秒。 提取批次数据大约需要。 2分钟

我正在使用以下内容来提取批次信息:

this.Context.Database.CommandTimeout = 2700;

Lot foundLot = EntitiesContext.Lots.Where(x => x.ID == lotID).FirstOrDefault();

this.Context.Database.CommandTimeout = 180;

我正在使用 Entity Framework Code First 中的迁移

 Database.SetInitializer(new MigrateDatabaseToLatestVersion<GenInspContext, Migrations.Configuration>());

当我创建表时,我将 cascadeDelete 设置为 true

.ForeignKey("dbo.Lots", t => t.LotID, cascadeDelete: true)

比起删除数据的 12 秒,我更关心提取数据所需的时间。

【问题讨论】:

这是什么意思? “站”是零件的结果 【参考方案1】:

延迟加载是开发人员使用 Entity Framework 遇到的第一个,可以说是最大的性能障碍。确保应用程序正常运行而不是抛出 NullReferenceExceptions 是一项很棒的功能,但如果您不考虑它,它绝对是性能杀手。

语句如下:

Lot foundLot = EntitiesContext.Lots.Where(x => x.ID == lotID).FirstOrDefault();

...看起来很无辜,它们是完全无害的实体的信息。这包括执行诸如序列化 Lot 以发送到 Web 客户端之类的操作。

默认情况下,每当 EF 加载包含 virtual 对其他实体的引用的实体时,除非您明确禁用延迟加载代理,否则 EF 将创建将跟踪这些相关实体的实体的代理。如果引用不是预先加载的并且代码尝试访问它,实体将检查它的 DbContext 是否仍然可用,并发出一个新的查询来获取被触摸的实体。

将此行为与序列化程序结合起来,从性能的角度来看,这会导致各种地狱。例如,如果一个 Lot 有一个 Parts 集合,每个 Part 都有一个 Stations 集合,我们加载 1 个 Lot,我们会得到:

SELECT * FROM Lot WHERE LotId = 1;

够无辜的。但是,如果我们的序列化程序或代码触及 Parts 集合,则会运行以下查询:

SELECT * FROM Parts WHERE LotId = 1;

现在加载了 100 个零件......不过,没有什么可真正关心的。然而,对象模型越嵌套,它很快就会变得越糟糕。在序列化程序的情况下,它将开始迭代每个部分,这涉及到 Stations 集合。现在便便开始撞击风扇:

SELECT * FROM Stations WHERE PartId = 1;
SELECT * FROM Stations WHERE PartId = 2;
SELECT * FROM Stations WHERE PartId = 3;
SELECT * FROM Stations WHERE PartId = 4;
SELECT * FROM Stations WHERE PartId = 5;
....
SELECT * FROM Stations WHERE PartId = 100;

之所以这样做(而不是JOINing Part on Station)是因为迭代涉及每个 Part 的 Station 集合。这会导致对 each 部分的 Stations 查询。如果每个部分有1-5个站。随着这些站被序列化,每个站的引用反过来会导致更多的查询,依此类推。您可以在应用程序运行时使用分析器观察 SQL 垃圾邮件的扩散。

快速解决方法是利用急切加载。这会将初始查询中的SELECT 垃圾邮件替换为JOINs。这可以使加载数据比依赖延迟加载更快。与等待 EF 组合和启动数万个查询的几分钟相比,具有各种内部和外部联接的查询可能需要几秒钟。但是,这里的考虑是您仍在从服务器加载潜在的垃圾数据。 EF 必须编写查询,将其发送到 DB 执行,DB Server 需要为所有结果分配空间,然后将这些结果通过网络传输回应用程序服务器,然后应用程序服务器必须为结果图,可能会将其序列化到客户端。随着应用程序的发展和新的关系被添加到现有实体中,这也会使地雷潜伏在您的应用程序中。一个新的关系被添加到图表的某个地方,在您知道之前,在完全未触及的区域(例如搜索)中突然出现了看似无关的性能问题,因为序列化程序现在正在拾取并加载那些未急切加载的实体。 (因为应用程序的这些区域不需要显示该信息。)

更好的解决方案是在读取要计算或序列化到客户端的数据时利用投影,并保存加载实体及其相关详细信息(如有必要)以用于更新操作等操作。使用 Select 或 Automapper 的 ProjectTo 方法的投影允许您编写填充安全、POCO 以进行序列化或匿名类型以检查和使用的查询,这将导致更远、更远、更快的查询和更小的数据负载发送过来电线。这样,查询只会加载它需要的信息,并且根据新关系对数据模型的更改永远不会污染现有的查询。那些现有的查询可以忽略新表,仅在实际需要考虑新数据时才更改。这种随时间变化的地雷效应是我提出的最大论据之一,即从不将实体发送到 Web 客户端。 (除了浪费时间/负载发送客户端不需要看到的数据,以及如果您从客户端接受实体返回潜在的安全问题。)

【讨论】:

最初我为此使用 JOIN 语句,但结果却比这种方式慢。我不确定为什么。我实际上已经下载了一个 nuget 包,我相信它被称为“ZExpressions”,它可以转换 Join 语句并为 EntityFramework 进一步优化它。您是否有推荐的方法来对这些表进行连接,您认为这比尝试仅在选择查询中选择批次信息要快?但是,您对它执行每个单独的选择是正确的。我注意到在为正在运行的进程列表拉取 MySQL 工作台时。 我们从不更新很多信息,一旦运行了一个批次,它就保持不变。所以我不需要专注于能够存储连接。 准备好的声明对此有帮助吗?如果我使用数据库迁移创建了一个准备好的语句,然后稍后调用它,这对速度有好处吗? 这个问题的答案将取决于需要如何使用数据。一次从相关表中提取数十万行是非常重要的。问题是“为什么”需要加载数据以及是否可以更有选择地或增量地完成。如果不需要编辑数据,那么拉取它 /w AsNoTracking 也是有益的,因为 DbContext 不会保留对检索到的预期数据更改的实体的引用。 另一个常见的陷阱是当您拥有相关数据并希望对相关集进行选择性处理时。例如想要加载一个批次,并且只加载符合特定标准的零件。 EF 可以支持一些基本的全局过滤,例如软删除 IsActive 或租赁,但除此之外,Lot.Parts 将始终获取该批次的 all 部分。在这些情况下,您可能希望使用 Select 来检索 Lot,忽略 Lot.Parts,然后选择 FilteredParts = x.Parts.Where(p =&gt; ...) 之类的东西作为所选匿名类型的一部分。

实体框架中多个“包含”的最佳实践是啥?

】实体框架中多个“包含”的最佳实践是啥?【英文标题】:Whatisthebestpracticeformultiple"Include"-sinEntityFramework?实体框架中多个“包含”的最佳实践是什么?【发布时间】:2013-07-0523:19:27【问题描述】:假设我们在数据模型... 查看详情

实体框架和 ASP.NET 的最佳实践

】实体框架和ASP.NET的最佳实践【英文标题】:BestPracticesforEntityFrameworkandASP.NET【发布时间】:2010-09-1422:42:59【问题描述】:我一直让自己发疯,试图让实体框架在ASP.NET环境中按预期(或至少按我预期)工作,特别是在尝试保存... 查看详情

n 分层架构中的实体框架 - 要遵循的最佳实践?

】n分层架构中的实体框架-要遵循的最佳实践?【英文标题】:EntityFrameworkinantieredarchitecture-BestPracticestofollow?【发布时间】:2010-12-2502:30:48【问题描述】:我一直在阅读MSDN文章http://msdn.microsoft.com/en-us/magazine/cc700340.aspx但想知道在... 查看详情

通过c#代码检索存储在sql表中的Json值的最佳实践

...我想检索该JSON值并将其绑定到C#属性(反序列化为所需的实体)。我想知道有效地做到这一点的最佳做法是什么?现在,我正在这样做:Public 查看详情

java spring web应用中实体本地化的最佳实践

】javaspringweb应用中实体本地化的最佳实践【英文标题】:Bestpracticeforentitieslocalizationinjavaspringwebapplications【发布时间】:2011-05-2613:08:54【问题描述】:我正在寻找在我的网站上本地化动态(用户生成)内容的最佳方式。我正在使... 查看详情

最佳实践:C# 扩展方法命名空间和推广扩展方法

...如何根据分配命名空间来组织扩展方法。目前-对于我们框架中的扩展方法-我使用以下命名空间模式MyCo 查看详情

转web程序优化的最佳实践:javascript和css篇

Yahoo!的ExceptionalPerformance团队为改善Web性能带来最佳实践。他们为此进行了一系列的实验、开发了各种工具、写了大量的文章和博客并在各种会议上参与探讨。最佳实践的核心就是旨在提高网站性能。ExcetionalPerformance团队总结出... 查看详情

实体框架长期数据上下文与短期数据上下文 [关闭]

】实体框架长期数据上下文与短期数据上下文[关闭]【英文标题】:Entityframeworklonglivingdatacontextvsshortlivingdatacontext[closed]【发布时间】:2017-04-1813:49:19【问题描述】:我想知道在以下两个示例之间使用C#和SQLServer(实体框架)的最... 查看详情

基于实体属性确保 CoreData 实体唯一的最佳实践

】基于实体属性确保CoreData实体唯一的最佳实践【英文标题】:BestPracticeforensuringCoreDataentitiesareuniquebasedonentityattributes【发布时间】:2011-02-0315:40:15【问题描述】:我要做的是确保我的图表中的实体是唯一的。例如,任何两个用... 查看详情

fetchedResultsController 获取带有谓词的实体的最佳实践

】fetchedResultsController获取带有谓词的实体的最佳实践【英文标题】:fetchedResultsControllerbestpracticesforgettingentitieswithpredicate【发布时间】:2012-03-2802:05:03【问题描述】:所以我有以下代码用于获取我的所有核心数据实体,称为设置-... 查看详情

C# 数据连接最佳实践?

】C#数据连接最佳实践?【英文标题】:C#DataConnectionsBestPractice?【发布时间】:2013-07-0707:57:16【问题描述】:好的,这是一种固执己见的话题,但根据您的知识、观点和当前实践,设置以下场景的最佳方法是什么?我正在构建一... 查看详情

在 C# 中实现加密和解密的最佳实践 [关闭]

】在C#中实现加密和解密的最佳实践[关闭]【英文标题】:bestpracticesofimplementingencryptionanddecryptioninC#[closed]【发布时间】:2011-09-2323:18:56【问题描述】:请分享在C#中实现加密和解密的最佳实践。如果可能,请参考一些代码。【问... 查看详情

关于最佳实践的 C# 神话?

】关于最佳实践的C#神话?【英文标题】:C#mythsaboutbestpractices?【发布时间】:2010-04-1211:09:26【问题描述】:我的同事一直告诉我cmets中列出的东西。我很困惑。有人可以为我揭开这些东西的神秘面纱吗?classBarprivateint_a;publicintAge... 查看详情

在 ASP.NET WebApi 中路由相关实体的最佳实践是啥

】在ASP.NETWebApi中路由相关实体的最佳实践是啥【英文标题】:WhatisthebestpracticetorouterelatedentitiesinASP.NETWebApi在ASP.NETWebApi中路由相关实体的最佳实践是什么【发布时间】:2015-11-2113:43:13【问题描述】:我正在使用具有链接实体的Web... 查看详情

DTO、DAO 和实体?是实体需要吗?那三个的最佳实践?

】DTO、DAO和实体?是实体需要吗?那三个的最佳实践?【英文标题】:DTO,DAOandEntity?IsEntityneeded?Bestpraticewiththose3?【发布时间】:2021-12-1908:37:09【问题描述】:我假设如果您使用的是DTO和DAO,则不需要实体,至少我以这种方式看到... 查看详情

C# 继承最佳实践

】C#继承最佳实践【英文标题】:C#Inheritancebest-practice【发布时间】:2011-12-1411:05:17【问题描述】:我有一个名为BaseView的普通类,它带有一个虚拟方法DisplayView。此方法调用GetHeader和GetBody虚拟方法来获取页面的内容。然后,我将... 查看详情

最佳实践? - 数组/字典作为核心数据实体属性 [关闭]

】最佳实践?-数组/字典作为核心数据实体属性[关闭]【英文标题】:Bestpractice?-Array/DictionaryasaCoreDataEntityAttribute[closed]【发布时间】:2009-10-1320:16:25【问题描述】:我是CoreData的新手。我注意到集合类型不能用作属性类型,并且... 查看详情

最佳实践? - 数组/字典作为核心数据实体属性 [关闭]

】最佳实践?-数组/字典作为核心数据实体属性[关闭]【英文标题】:Bestpractice?-Array/DictionaryasaCoreDataEntityAttribute[closed]【发布时间】:2009-10-1320:16:25【问题描述】:我是CoreData的新手。我注意到集合类型不能用作属性类型,并且... 查看详情