过度使用 DataTable 是否很糟糕?
Posted
技术标签:
【中文标题】过度使用 DataTable 是否很糟糕?【英文标题】:Is excessive DataTable usage bad?过度使用 DataTable 是不是很糟糕? 【发布时间】:2010-12-09 11:41:15 【问题描述】:我最近被要求协助另一个团队构建一个 ASP .NET 网站。他们已经编写了大量代码——我被特别要求为该网站构建几个单独的页面。
在探索网站其余部分的代码时,正在构建的 DataTables 的数量让我大吃一惊。作为该领域的一个相对较新的人,我从来没有开发过像这个站点那样使用数据库的应用程序,所以我不确定这有多普遍。似乎每当从我们的数据库中查询数据时,结果都存储在 DataTable 中。然后这个 DataTable 通常会自行传递,或者传递给构造函数。使用 DataTable 初始化的类总是将 DataTable 分配给私有/受保护的字段,但是这些类中只有少数实现了 IDisposable。事实上,到目前为止,在我浏览的数千行代码中,我还没有看到在 DataTable 上调用的 Dispose 方法。
如果有的话,这似乎不是一个好的 OOP。这是我应该担心的事情吗?还是我只是比我应该更关注细节?假设您是比我最有经验的开发人员,如果刚刚被指派帮助您开发网站的人就这个“问题”与您联系,您会有什么感觉或反应?
【问题讨论】:
我不是 OOP。一些 OOP 技术仍然可以使用,但是定义 OOP 甚至类型变量的许多限制很容易绕过。如果您曾经在干净的 OOP 环境中工作,您会觉得相当……不舒服。 【参考方案1】:在非常高的层次上,软件系统架构可以被描述为使用几种“企业级模式”之一,Transaction script、Table Model、Domain Model 或 Service Layer。如果您正在审查的系统使用 Table Model 模式,那么您会期望看到比在使用 Domain Model 设计的系统中更多地使用 DataTables 和 DataSets em> 或其他模式之一。
然而,随着过去几年软件系统设计方法的发展,人们普遍认为复杂系统不能很好地使用事务脚本或表模型架构。这通常是因为在使用这些模式设计的系统中,功能通常更加交织和相互关联,并且随着复杂性的增长,功能或模块相互依赖的数量呈指数增长,并且变得难以快速管理。因此,根据您的特定系统的复杂程度,是的,如果在系统的多个层中使用 DataSet 和/或 DataTables,您应该怀疑。这可能表明系统设计者曾经/正在使用表模型(有意或无意地)他/她应该使用域模型或服务层架构。
【讨论】:
是的,我认为您可以轻松地将“Table Model”替换为“Design Fail” @Chris,你把没用的 cmets 放在这里。如果你这样做了,那么请添加几行来解释为什么 DataTables 是一种不好的做法。 @Javis,您是否真的在争论 DataTables 自从泛型在 .NET 2.0 中发布以来存在任何用途? @Chris,不,他只是建议当您发表负面评论时,添加一些事实以帮助读者理解您的观点。这个论坛是为了帮助人们,而不是炫耀你有多聪明。 你能看看这个问题,它是相关的吗? ***.com/questions/18562928/…【参考方案2】:数据表可用于善恶。
可接受的使用
我认为以下是可接受的数据表或数据行用法:
public class User
private DataRow Row get; set; ;
public User(DataRow row) this.Row = row;
public string UserName get return (string)Row["Username"];
public int UserID get return (int)Row["UserID"];
public bool IsAdmin get return (bool)Row["IsAdmin"];
// ...
上面的类是ok,因为它将DataRow 映射到一个类型安全的类。现在您可以使用真正的数据类型和智能感知来帮助您,而不是使用字符串和无类型的数据行。此外,如果您的数据库架构发生更改,您可以修改对象中的列名,而不是在任何使用它的地方修改列名。最后,您可以将难看的列名(例如“dtaccount_created”)映射到名为“AccountCreated”的属性。
当然,编写这个包装类确实没有什么好理由,因为 Visual Studio 会自动为您生成typed datasets。或者,作为替代方案,像 NHibernate 这样好的 ORM 允许您定义与上述类似的类。
您应该使用普通的旧 ADO.NET、类型化数据集还是完整的 ORM,取决于您的应用程序的要求和复杂性。如果没有实际看到一些示例代码,很难说您的团队是否在做正确的事情。
此外,我偶尔会发现将列表和网格与数据表进行数据绑定很有用,因为对底层数据行的更改会自动导致 GUI 刷新。如果您创建自己的类型安全包装器,则需要手动实现 IPropertyChanging 和 IPropertyChanged 接口。
不可接受的使用
不幸的是,我看到程序员将数据表用于临时容器、类的替代品等。如果您看到您的团队这样做,请向他们扔石头。这种编程风格在静态类型语言中是行不通的,它会让开发成为一场噩梦。
数据表的主要问题:它们没有类型,所以如果不给它们一个字符串并将它们包含的任何神秘对象转换为正确的类型,你就无法对它们做任何有用的事情。此外,重构列名几乎不可能自动化,因为它们是基于字符串的,因此您不能依赖智能感知来帮助您编写正确的代码,也无法在编译时捕获错误。
我说相信你的直觉:如果你认为设计是脆弱的,它可能就是。
【讨论】:
不可接受的使用 我的公司在其他程序员开发的每个项目中都有完全相同的问题,这真是一场噩梦。在使用 ORM、设计模式、MVC、lambda 表达式等之后,它看起来很恐怖。尽可能避免这种情况。 作为补充,您应该使用 DataRow 的 .Field使用 DataTable 可能是一种懒惰/低效的数据存储方式。这样做有很大的开销。您的担心是对的,尽管开发人员可能在听到他们设计此应用程序的糟糕程度时遇到了真正的问题。管理层会在你创造更优质产品的目标中支持你吗?他们可以接受相关的开发延迟吗?
【讨论】:
懒惰是如何低效的?如果我认为情况正好相反? 是的,请解释一下,我厌倦了阅读不正确的陈述而对底层机制知之甚少。【参考方案4】:这绝对是您应该担心的事情 - 请参阅相关帖子 on the importance of Disposing DataTables。
DataTables是可终结的:如果您不主动处置它们,它们会比 Gen0 集合停留更长的时间并消耗内存。
要测量应用程序的损坏程度,您可以使用 WinDbg 进行内存转储并查看 DataTable 实例的绝对数量(!dumpheap -stat -type System.Data.DataTable)然后看看largest data tables in memory。
这是 ASP.NET 应用程序中的一个常见缺陷,可能会给您带来严重的麻烦。如果您使用共享(缓存)数据表实例,请注意视图过滤器会更改原始实例,它们不会生成新副本。
还要确保填充 DataTables 的查询对返回的行数有合理的限制,否则对数据的更改可能会突然增加内存并破坏应用程序池的稳定性。
【讨论】:
DataTable 不需要被释放,它们是托管对象。这个答案是比较苹果和橙子。在应用程序池被回收之前,您放入 ASP.NET 缓存中的任何内容都可以保存在那里,这不是特定于 DataTable 的。 ...和Cases
无法最终确定? (所有课程都是)我相信这整个答案是有缺陷的,请仔细检查你在说什么。您所说的所有内容都可以应用于泛型,如果您打算将其用作替代方案,如果不是,请解释。【参考方案5】:
是的,我会在这里小心...
我必须照顾一个 vb.net 网络应用程序大约 2 个月,然后才能用 C# 重新编写它......我喜欢 C#,VB 让我想投掷......
无论如何,在旧应用程序中,之前的开发人员已将数据库中的数据加载到数据表中,然后将数据表传递给一些对数据表完全没有任何作用的方法,只是将其分配给网格视图。我完全不相信。
更糟糕的是,有时他实际上会无缘无故地将 DataTable 转储到会话中。
DataTables 等很棒,但只有在你“真的”需要使用它们时才使用它们。开发人员太糟糕了,在搜索页面上,他实际上将所有 5000 种产品从数据库中转储到数据表中,然后在数据表上执行搜索,而不是在存储过程中执行搜索(即在 SQL SERVER 上)
【讨论】:
对于只有 5000 个产品的数据库(取决于产品的复杂性)的最后一段,将整个表缓存在内存中可能是最好的解决方案,并直接在 C# 中处理搜索。当然,我怀疑他在获得 5000 行后是否真的缓存了表格...... @Dal:不管怎样,会话中一些不必要的参数和不必要的对象是可以原谅的;并且存储保留 5000 个对象的数据表以供本地查询有时在内存和速度方面可能优于数据库。不,TRWTF 完全重写了从 VB.NET 到 C# 的工作应用程序,因为它不是你最喜欢的宠物语言。克服自己。 @Chris... 搜索的是面向公众的网站上的产品页面,您只需输入几个关键字,它将搜索诸如“颜色、细节、ShortDetail、尺寸”等字段...我不知道,但是在 asp.net 页面(业务层)中执行此逻辑对我来说似乎不是拥有这么多记录的最佳方法...因为它已被重写以执行搜索逻辑无论如何,在 SP 中它已经快得多了。 @Juliet vb.net 应用程序充满了错误,无论如何都需要重写 - 一旦老开发人员离开,我就接管了......我被聘为 C# 开发人员,管理层同意了事先所有应用程序都需要在 C# 中。当您使用 Java、C#、php 时,必须使用 VB.NET 可能是像我这样的“某些”开发人员所能做的最痛苦的事情............ ....然后是 VB.NET waaaaaay 在神秘的“DIM”土地上 这个答案与它的使用方式有关,而不是作为一个整体。如果你写了糟糕的代码,那么它就是糟糕的代码。尝试用作缓存...未正确实现不会使数据表变坏,只会导致代码不完整。 aka 如果他用作缓存,它足够聪明,知道何时从 db 加载并且不知道什么时候加载,那么它会很好用......就像我说的与数据表本身无关。以上是关于过度使用 DataTable 是否很糟糕?的主要内容,如果未能解决你的问题,请参考以下文章