以下是我的情况:我试图尽可能地遵循3层模式(即演示文稿,业务和数据层)。当我需要来自数据库的数据时,业务层调用返回信息的数据层。数据层永远不会返回SqlDataReader或DataTable对象,但通常是数据访问层已知的自定义对象的枚举。当数据层必须返回包含少量对象的列表时,它的效果非常好。
我现在面临这个问题,我的应用程序(业务层)必须处理500000条记录。我可以简单地向我的数据层添加另一个方法并返回一个IEnumerable,但这听起来非常糟糕。我不想在内存中加载50万条记录。
我的问题是,考虑到3层模型,我该如何处理这个案例?如果我没有3层模式,我只需在业务类中使用SqlDataReader。有什么建议吗?
UPDATE :数据不会显示,因此这不是分页问题(此处根本不涉及表示层)。我只需要分析每条记录,然后保留其中一些记录。
由于
答案 0 :(得分:2)
我假设您不是一次向前端显示500,000条记录?你可能正在做一些分页,对吗?因此,一次只能从数据库返回一页数据。
答案 1 :(得分:1)
是的,你的直觉是正确的。
我打赌你的UI客户端不想一次查看50万条记录。 Google不会在单个页面中返回每个匹配项;你也不会。
您可以选择应用程序处理这50万条记录的位置和时间。你可以将它们分成更小的工作单元;你可以异步处理它们;您可以编写存储过程并在数据库中处理它们,而不必将它们全部带到中间层。
MVC模式很棒,但它不是神圣的。做出适合您应用的选择。
答案 2 :(得分:1)
一张纸永远无法胜过现实。如果你的具体问题要求打破三层范式,那就去做吧。
答案 3 :(得分:1)
在某些情况下,您必须打破3层边界。但在你做之前,你可以问自己:
当你“分析每条记录然后保留其中一些记录”时,它真的是业务逻辑的一部分吗?或者它是数据访问功能?可能是这属于数据访问层。
如果是业务逻辑的一部分,您是否需要所有500000条记录才能决定是否“保留”任何单个记录?可能是业务层应该一次处理一条记录。进行500000次连续数据库调用并不是很好,但如果这是应用程序应该从概念角度进行的操作,那么有一些方法可以减轻这种影响。
我不建议做任何愚蠢的事情只是为了保持3层分开。但有时候,当你认为必须跨越界限时,这是因为设计中有一些东西需要重新审视。
-
BMB
答案 4 :(得分:1)
您可以在SqlReader类之上构建抽象。这样您就不必直接传递SqlReader,但您仍然可以一次处理一个对象。
思考迭代器。
答案 5 :(得分:1)
在数据库中进行过滤。无论如何都不需要带来超过500000条记录。为什么要将它们全部带到中间层才能删除它们。使用后端的SQL引擎(sproc)尽早处理操作(数据)。效率最高,类似于在发送到IIS之前检查表示层上的基本输入检查。
答案 6 :(得分:0)
这不是一个罕见的问题,并且在您需要合并大量数据并向用户提供摘要的情况下经常出现(报告是典型示例)。您的解决方案应该考虑到这些因素。当某些特定架构模型的严格一致性使您的应用程序效率低下时,忽略sql读取器(或类似工具)提供的效率是没有意义的。通常可以通过根据您的需求调整架构模型来克服其中一些问题。通用架构模型很少开箱即用。它们是应该适用于您特定需求的指南。
答案 7 :(得分:0)
在数据库级别进行任何需要的分析都没有羞耻感。如果您可以使用存储过程切片和切块,或者与存储过程进行必要的关联,并使用应用程序进行更复杂的操作,那么您应该没问题。
问题是,用户是否希望按下按钮并处理所有500K记录并查看结果?如果是这样,他们是否愿意坐下来观看旋转的gif,或者在完成该过程后收到某种类型的通知是否令人满意?如果处理500K是最重要的,那么您的数据模型是否需要更改以支持此过程?有Hadoop和message queues等处理方法适合这种高容量,但是你需要达到这个程度吗?您可以先设定用户的期望,然后再将性能提升到最佳状态。
答案 8 :(得分:0)
如果我正确地理解了这一点,你想要“分析”这些记录,然后保留其中一些记录并摆脱其余的记录。那么在这种情况下我认为最好在数据库本身(PL / SQL或T / SQL)中处理这个问题。这些要求应该是首要任务,而不是架构。由于您不是仅仅展示分析,因此最好在程序本身中进行。