DAL 数据集与集合






1.80/5 (4投票s)
演示了如何通过 DAL 创建一个可数据绑定的强类型集合,以替代 DataSet。
引言
在本文中,我将引导您创建一个示例 Web 应用程序,该应用程序将从数据库打印数据列表。我们不使用数据集,而是使用一个强类型集合,该集合将利用泛型。令人惊讶的是,这种更高级的数据处理方法实现起来非常简单。
背景
我们现在正处于重构的天堂(至少我认为是天堂,呵呵)。我和我的同事们一直在头脑风暴,思考我们不喜欢应用程序的哪些部分,以及我们理想中想做什么,这时有人提出,集合对于我们的系统来说可能比数据集更有价值。我做了一些研究,偶然发现了以下关于这个主题的文章:MSDN:数据集与集合。我可以为您节省一些阅读时间。基本上,如果您具备相关知识,公司能承受时间投入,并且在大多数 SQL 事务中通常返回 1000 多行数据,那么您应该做类似的事情。
这是一个通用规则。在我工作的地方,过去我们一直使用数据集处理一切。数据集带来了很多开销,而我们实际上只利用了 15% 的时间。这对我们来说是一个很好的替代方案,它运行更精简,并且提供了我们所需的最少功能。
此外,您会注意到我在这个项目中大量使用了 OOP。通常情况下,我不会在这么小的项目中使用 OOP,因为它有些多余。然而,这是一个如何在我日常工作中处理中等规模项目代码的示例。您可以随意根据自己的喜好进行简化。
Using the Code
首先,您需要 Microsoft 的示例 AdventureWorks 数据库。您可以在此处下载:AdventureWorks 示例数据库。
为了进一步简化,我们暂时将测试驱动开发放在一边。
让我们从查看期望的最终产品开始,然后倒推。
LoginID | EmployeeID (员工编号) |
---|---|
adventure-works\guy1 | 1 |
adventure-works\kevin0 | 2 |
adventure-works\roberto0 | 3 |
adventure-works\rob0 | 4 |
等等...
简单、不好看,但功能齐全。我们只是创建一个表来关联 LoginID
和 EmployeeID
。这在现实世界中有何用处?我不知道……审计?无论如何,这是一个简单的例子,它将(暂时)教您关于列表、泛型以及将 GridView
数据绑定到基于集合的数据源所需的一切。
既然我们知道目标是什么,让我退一步,我们先只看网页中的代码(稍后我们会看类对象和 DAL)。我喜欢列出我使用的所有命名空间,因为在学习代码教程时,我讨厌费力地去查找它们。
using System;
using System.Data;
using System.Configuration;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Web.UI.HtmlControls;
using HR;
public partial class _Default : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
Employees AllEmployees = new Employees();
this.EmployeesGridView.DataSource = AllEmployees;
this.EmployeesGridView.DataBind();
}
}
这就足够使用我创建的对象了。我们有一个 Employees
类。这实际上是我们的数据集合。实例化集合后,其构造函数会查询数据库并提取所有员工的列表,正如您将在下一个示例中看到的。在第一个示例中,我将再次列出命名空间,因为这是我们第一次使用这个特定的命名空间。
using System;
using System.Collections.Generic;
using System.Data;
using System.Data.Sql;
using System.Data.SqlClient;
using System.Text;
using DbDAL;
namespace HR
{
public class Employees : List<IEmployee>
{
public Employees()
{
//This should not be hard coded but it's
//an example. Oh well! ;)
string SqlQuery = "select * from HumanResources.Employee";
IEmployee AnEmployee;
SqlDataReader MySqlReader = DBHelper.ExecuteQuery(SqlQuery);
while (MySqlReader.Read())
{
AnEmployee = new Employee();
AnEmployee.EmployeeID = (int)MySqlReader["EmployeeID"];
AnEmployee.LoginID = (string)MySqlReader["LoginID"];
this.Add(AnEmployee);
}
MySqlReader.Close();
}
}
好的。更复杂一些,但仍然相当紧凑。总体概述是这样的:Employees
本质上是一个列表,它会自行获取数据并填充自身。它也是一个强类型列表,因此您无需执行任何转换。每当进行转换时,您都会面临两个主要风险:运行时错误,因为您无法 100% 确定要转换的数据类型,以及性能下降。我们使用泛型(<iemployee>
)将列表变成 IEmployee
的强类型集合。当我们要向集合中添加项时,只需引用“this
”对象并调用 Add
方法。
接下来,从数据库读取数据到一个在此命名空间中定义的结构体。这个结构体专门用于此记录集。我偏爱这种方式,因为它基本上使我们的方法具有自我描述性。如果我需要知道此代码期望什么类型的数据,只需检查与我的数据访问方法关联的结构体即可得知。
现在,对于每一行新数据,我们创建一个新的结构体来存储它,然后将该结构体放入我们的集合(在这种情况下是“this
”)并重复。您会注意到我确实需要从我的 DataReader
进行一次初始转换到我的结构体。我不知道有办法规避这一点。除此之外,如果每个项只需转换一次,我认为我们就比大多数代码做得更好了。
首先,我声明了我的结构体。请注意,我在这里是面向接口编程。这是一个非常小的教程,但由于我们正在为企业级项目进行练习,我宁愿保持这些习惯。接下来,我通过硬编码获取我的查询。是的,我知道这不好。不要像我这样做!我使用我的 DBHelper
对象来运行查询并返回一个 DataReader
,我可以遍历它来填充我的列表。如果您想了解我选择 DataReader
而非 DataSet 的原因,可以阅读以下文章:DataReader 与 DataSet。可以说,对于将数据从数据库直接拉取到数据结构中,没有任何东西比 DataReader
更高效。
public struct Employee
{
private int _employeeID;
private string _loginID;
public int EmployeeID
{
get
{
return _employeeID;
}
set
{
_employeeID = value;
}
}
public string LoginID
{
get
{
return _loginID;
}
set
{
_loginID = value;
}
}
}
这是 Employee
结构体的接口。我为结构体创建了一个接口,因为我工作的地方的代码支持 .NET Remoting。在这种情况下,将结构体设置为接口允许任何能够与我的代码交互的人知道预期的数据是什么。在我看来,这是自我描述代码的一个理想示例。如果您想更好地了解,我已经附加了所有示例代码。
关注点
这里需要注意的一些事情是,要考虑您计划如何使用您的数据。如果您要进行过滤和排序,那么使用数据集可能更好。但是,如果您的 DAL 的大部分内容与我见过的相似,那么您很可能只需返回所有结果作为对象即可。
历史
- 我相信该代码可以标记为
ISerializable
,以便通过 Web 服务使用。 - 将文章放置在 .NET 编程部分,而不是 .NET 数据库部分。
- 进行了一些编辑。删除了接口,并用结构体替换了它。