过度的DataTable使用不好吗?

时间:2009-10-23 14:23:09

标签: c# asp.net

我最近被要求协助其他团队建立ASP .NET网站。他们已经编写了大量代码 - 我被特别要求为该网站构建一些单独的页面。

在探索网站其余部分的代码时,正在构建的DataTable的数量向我跳出来。作为一个相对较新的领域,我从来没有像使用这个网站那样使用数据库的应用程序,所以我不确定这是多么常见。似乎每当从我们的数据库查询数据时,结果都存储在DataTable中。然后,此DataTable通常自行传递,或者传递给构造函数。使用DataTable 初始化的类始终将DataTable分配给私有/受保护字段,但这些类中只有少数实现IDisposable。实际上,到目前为止我浏览过的数千行代码中,我还没有看到在DataTable上调用Dispose方法。

如果有的话,这似乎不是好的OOP。这是我应该担心的吗?或者我只是比我更注重细节?假设您是最有经验的开发人员,如果刚刚被指派帮助您访问您网站的人向您询问此“问题”,您会有什么感受或反应?

5 个答案:

答案 0 :(得分:21)

数据表可以用于善恶。

可接受的使用

我会发现以下内容是数据表或数据行的可接受用法:

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映射到typesafe类。现在你有了真正的数据类型和intellisense来帮助你,而不是使用字符串和无类型的数据行。此外,如果数据库架构发生更改,则可以修改对象中的列名,而不是在其使用的任何位置修改列名。最后,您可以将丑陋的列名称(如“dtaccount_created”)映射到名为“AccountCreated”的属性。

当然,写这个包装类真的没有理由,因为Visual Studio会自动为你生成typed datasets。或者,作为替代方案,像NHibernate这样的好的ORM允许您定义类似于上面的类。

您是否应该使用普通的旧ADO.NET,键入的数据集或完整的ORM取决于应用程序的要求和复杂性。很难说你的团队是否做了正确的事情,实际上看到了一些示例代码。

此外,我偶尔会发现使用数据表对数据列表和网格进行数据绑定很有用,因为对基础数据行的更改将自动导致GUI刷新。如果您创建自己的类型安全包装器,则需要手动实现IPropertyChanging和IPropertyChanged接口。

不可接受的使用

不幸的是,我见过程序员使用数据表作为临时容器,类的替代品等等。如果你看到你的团队这样做,就向他们扔石头。这种编程风格不适用于静态类型语言,它会使开发成为一场噩梦。

数据表的主要问题:它们没有输入,所以你不能对它们做任何有用的事情而不给它们一个字符串并将它们包含的任何神秘对象转换成正确的类型。此外,重构列名几乎不可能自动化,因为它们基于字符串,因此您不能依靠intellisense来帮助您编写正确的代码,并且您无法在编译时捕获错误。

我说相信你的直觉:如果你认为设计很好,那很可能就是。

答案 1 :(得分:7)

这绝对是您应该担心的问题 - 请参阅相关帖子on the importance of Disposing DataTables

DataTables 可以最终确定:如果你没有主动处理它们,它们会比Gen0集合更长时间地停留并杀死内存。

要测量应用程序中的损坏程度,可以使用WinDbg进行内存转储,并查看大量的DataTable实例(!dumpheap -stat -type System.Data.DataTable )然后查看largest data tables in memory

这是ASP.NET应用程序中常见的陷阱,可能会给您带来严重的麻烦。如果您正在使用DataTables的共享(缓存)实例,请注意视图筛选器会更改原始实例,但它们不会生成新副本。

还要确保填充DataTables的查询对返回的行数有一些合理的限制,否则对数据的更改可能会突然变为内存并破坏应用程序池的稳定性。

答案 2 :(得分:5)

在很高的层次上,软件系统架构可以表征为使用多种“企业级模式”之一,Transaction scriptTable ModelDomain ModelService Layer 。如果您正在查看的系统正在使用表模型模式,那么您可能希望看到更多使用DataTables和DataSet,而不是使用 Domain Model 或其他模式之一。

然而,随着软件系统设计方法在过去几年中不断发展,人们普遍认为复杂系统使用事务脚本或表模型架构并不是很好。这通常是因为在使用这些模式设计的系统中,功能通常更加交织,相互关联,并且随着复杂性的增加,功能或模块相互依赖的数量呈指数级增长,并且变得难以快速管理。因此,根据您的特定系统的复杂程度,是的,如果在系统的多个层中使用DataSet和/或DataTable,您应该怀疑。这可能表明系统设计人员正在使用表模型(有意识或无意识地),他/她应该使用域模型或服务层架构。

答案 3 :(得分:3)

是的,我会在这里小心......

我不得不照看一个vb.net网络应用程序大约2个月才能用C#重新编写它....我喜欢C#,VB让我想要投掷......

无论如何,在旧的应用程序中,以前的开发人员已经将数据库中的数据加载到数据表中,然后围绕几个方法传递数据表,这些方法对数据表没有任何作用,只是将它分配给gridview。我完全不相信。

更糟糕的是,有些时候他实际上会将DataTable转储到会话中......完全没有理由。

DataTables等很棒,但只有在你真的需要使用它们时才使用它们。开发人员太糟糕了,在搜索页面上,他实际上将数据库中的所有5000个产品转储到数据表中,然后在数据表上执行搜索,而不是在存储过程中执行搜索(即在SQL SERVER上)

答案 4 :(得分:1)

使用DataTable可能是一种存储数据的惰性/低效方式。这样做有很大的开销。你是正确的,虽然开发人员可能有一个真正的问题,听到他们设计这个应用程序有多糟糕。在您创造更优质产品的目标中,管理层是否会支持您?相关的发展延迟是否可以接受?