我最近被要求协助其他团队建立ASP .NET网站.他们已经编写了大量的代码 - 我被特别要求为该网站构建一些单独的页面.
在探索网站其余部分的代码时,正在构建的DataTables的数量向我跳出来.作为一个相对较新的领域,我从来没有像使用这个网站那样使用数据库的应用程序,所以我不确定这是多么常见.似乎每当从我们的数据库查询数据时,结果都存储在DataTable中.然后,此DataTable通常自行传递,或者传递给构造函数.使用DataTable初始化的类始终将DataTable 分配给私有/受保护字段,但是这些类中只有少数实现IDisposable.实际上,到目前为止我浏览过的数千行代码中,我还没有看到在DataTable上调用Dispose方法.
如果有的话,这似乎不是好的OOP.这是我应该担心的吗?或者我只是比我更注重细节?假设您是最有经验的开发人员,如果刚刚被指派帮助您访问您网站的人向您询问此"问题",您会有什么感受或反应?
数据表可以用于善恶.
可接受的使用
我会发现以下是数据表或数据行的可接受使用:
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"]; } } // ... }
上面的类是好的,因为它映射一个DataRow的类型安全类.现在你有了真正的数据类型和intellisense来帮助你,而不是使用字符串和无类型数据行.此外,如果数据库架构发生更改,则可以修改对象中的列名,而不是在其使用的任何位置修改列名.最后,您可以将丑陋的列名称(如"dtaccount_created")映射到名为"AccountCreated"的属性.
当然,编写这个包装类真的没有理由,因为Visual Studio会自动为你生成类型化的数据集.或者,作为替代方案,像NHibernate这样的好的ORM允许您定义类似于上面的类.
您是否应该使用普通的旧ADO.NET,键入的数据集或完整的ORM取决于应用程序的要求和复杂性.很难说你的团队是否做了正确的事情,实际上看到了一些示例代码.
此外,我偶尔会发现使用数据表对数据列表和网格进行数据绑定很有用,因为对基础数据行的更改将自动导致GUI刷新.如果您创建自己的类型安全包装器,则需要手动实现IPropertyChanging和IPropertyChanged接口.
不可接受的使用
不幸的是,我见过程序员使用数据表作为临时容器,类的替代品等等.如果你看到你的团队这样做,就扔石头.这种编程风格在静态类型语言中不起作用,它会使开发成为一场噩梦.
数据表的主要问题:它们没有输入,所以你不能对它们做任何有用的事情而不给它们一个字符串并将它们包含的任何神秘对象转换成正确的类型.此外,重构列名几乎不可能自动化,因为它们基于字符串,因此您不能依靠intellisense来帮助您编写正确的代码,并且您无法在编译时捕获错误.
我说相信你的直觉:如果你认为设计很好,那很可能就是.
这绝对是您应该担心的问题 - 请参阅有关Disposing DataTables重要性的相关文章.
DataTables 可以最终确定:如果你没有主动处理它们,它们会比Gen0集合更长时间地停留并杀死内存.
要测量应用程序中的损坏程度,可以使用WinDbg进行内存转储,并查看大量的DataTable实例(!dumpheap -stat -type System.Data.DataTable),然后查看内存中最大的数据表.
这是ASP.NET应用程序中常见的陷阱,可能会给您带来严重的麻烦.如果您正在使用DataTables的共享(缓存)实例,请注意视图筛选器会更改原始实例,但它们不会生成新副本.
还要确保填充DataTables的查询对返回的行数有一些合理的限制,否则对数据的更改可能会突然变为内存并破坏应用程序池的稳定性.
在很高的层次上,软件系统架构可以表征为使用多种"企业级模式", 事务脚本, 表模型, 域模型或 服务层之一.如果您正在查看的系统正在使用表模型模式,那么您可能会看到比使用域模型或其他模式之一设计的系统更多地使用DataTable和DataSet .
然而,随着软件系统设计方法在过去几年中不断发展,人们普遍认为复杂系统使用事务脚本或表模型体系结构并不是很好.这通常是因为在使用这些模式设计的系统中,功能通常更加交织,相互关联,并且随着复杂性的增加,功能或模块相互依赖的数量呈指数级增长,并且变得难以快速管理.因此,根据您的特定系统的复杂程度,是的,如果在系统的多个层中使用DataSet和/或DataTable,您应该怀疑.这可能表明系统设计人员正在使用表模型(有意识或无意识地),他/她应该使用域模型或服务层架构.