65.9K
CodeProject 正在变化。 阅读更多。
Home

ASP.NET 中使用 XQuery 和反射进行批量 CRUD 操作

2010年11月30日

CPOL

5分钟阅读

viewsIcon

66302

downloadIcon

1540

使用 Xquery、反射在 ASP.NET 中实现批量 CRUD 操作的简单方法,附带示例

引言

在数据库术语中,CRUD 代表四种基本数据库操作:创建(Create)、读取(Read)、更新(Update)和删除(Delete)。无论应用程序如何多样,大多数现实世界的应用程序都是以数据为中心,更确切地说,是以 CRUD 为中心。在某个时候,用户的大量数据需要写入数据库。通常,这通过重复的 DML 数据库调用来完成。更大数量的数据需要更昂贵的数据库调用(在内存和进程方面),并且会带来更大的数据不一致风险。如果我们能够以最少的数据库调用来完成操作,我们就可以实现更快的处理速度、更一致的数据以及更好的用户体验。考虑到这一点,在我一个大型数据驱动的项目中,我使用了 xml/xquery 进行 CRUD 操作,并希望通过一个简单的例子分享。

使用 XML 进行 CRUD?

XML 在现代信息系统、工业、政府和学术界得到广泛应用。许多商业数据库管理系统支持 XML 存储。然而,由于它们类型系统的表达能力差异以及将对象查询翻译成 XQuery 等 XML 查询语言的难度,自动进行 XML 和对象之间的翻译问题在很大程度上仍未解决。在混合关系/XML 数据库中,由于 XML 数据可以分布在多个关系表中,对象-关系阻抗不匹配问题使得这个问题更加复杂。SQL Server 2005 中引入了备受赞誉的 XML 数据类型。这种新的数据类型允许创建专门用于存储 XML 数据的变量和列,无论是整个 XML 文档还是其中的一部分内容。

使用 XQuery 进行 CRUD

XML 最新的发展之一是出现了原生的 XML 查询和转换语言 XQuery。XQuery 通常是完美的语言,它提供了一种简单优雅的方式来计算 XML 文档内容的值。使用 XML 而不是典型的 CRUD 操作方法的几个原因。这些原因包括:

  1. 最佳性能,TSQL 使用 XQuery 解析 XML 速度极快
  2. 将 CRUD 逻辑与应用程序的层分离
  3. 防止 SQL 注入攻击
  4. 节省应用程序到数据库的往返时间

SQL Server 在基于集合的操作方面表现最佳。逐行更新比一次更新多行要慢。在我们的示例中,假设营销人员想更改客户 ID 为 1、3、5 的电子邮件 ID,他们会选择数据网格中的项目,指定新的电子邮件 ID,然后单击“保存”按钮。您如何将 ID 列表作为表传递给 SQL Server?最简单的方法是将 ID 作为 XML 数据类型实例传递,然后使用nodes()value()方法将 XML 实例转换为表,并将该表与Product表连接。这样,更新就是基于集合的。

示例问题场景

假设我们要为营销系统构建一个仪表板,营销人员可以不断输入潜在的新客户信息并更新现有客户信息。需求是,通过仪表板,营销人员可以一次输入多个客户信息并保存所有数据,而不是让营销人员更新/插入单个记录。您可以看到,下面是应用程序仪表板 UI,营销人员可以通过点击“添加更多”按钮来添加多个客户。批量 CRUD 操作通过“全部保存”/“全部更新”/“全部删除”按钮来完成。

图:示例应用 UI

问题的解决方案

上述场景的功能可以通过使用 xml/xquery 轻松实现。我们可以将实现步骤总结如下:

  • 我们需要一个自定义类,其中包含在数据库中进行insert/update/delete操作所需的所有客户属性。
  • 根据每个客户填充该类,并在运行时形成一个集合。
  • 使用反射将该集合转换为内存中的 XML 格式。
  • 将此格式化的 XML 作为参数值传递给数据库存储过程以进行 CRUD 操作。
  • 使用 xquery,我们将解析参数值并根据需要应用 DML。

使用此方法的优点是:

  • 我们可以使用最少的参数将数据传递给数据库(更准确地说,只需要传递一个 XML 类型的参数)。
  • 我们可以一次性传递大量数据进行 CRUD 操作。
  • 随着数据量的增长,这不会影响应用程序的数据库调用。
  • 维护数据完整性很简单。
  • 由于数据结构灵活,未来在 DAL(数据访问层)中进行更改很容易。

实现

现在我将按照上述步骤实现解决方案。对于这个特定的实现,我将使用上面提到的问题场景并相应地实现。在获得想法后,您可以根据需要自定义以实现您版本的解决方案。我们将创建一个实体类来保存客户属性,并将其命名为Customer。该类将在 UI 的每次update/save事件后填充,并添加到customerList集合中以进行批量操作。我们将使用反射将此集合转换为 XML。

foreach (Customer xml in customerList)
{
    XmlElement element = doc.CreateElement("data");
    PropertyInfo[] allProperties = xml.GetType().GetProperties();
    foreach (PropertyInfo thisProperty in allProperties)
    {
        object value = thisProperty.GetValue(xml, null);
        XmlElement tmp = doc.CreateElement(thisProperty.Name);
        if (value != null)
        {
            tmp.InnerXml = value.ToString();
        }
        else
        {
            tmp.InnerXml = string.Empty;
        }
        element.AppendChild(tmp);
    }
    node.AppendChild(element);
}   

转换后,生成的 XML 将如下所示:

图:类到 XML 的映射

生成 XML 后,会将此 XML 作为参数传递给 SQL Server 存储过程。

using (SqlConnection cn = new SqlConnection(GetConnectionString()))
{
    SqlCommand sqlCmd = new SqlCommand();
    sqlCmd.Connection = cn;
    sqlCmd.Connection.Open();
    sqlCmd.CommandType = CommandType.StoredProcedure;
    sqlCmd.CommandText = "spr_Sync_Customer";

    sqlCmd.Parameters.Add("@XMLDATA", SqlDbType.Xml, Int32.MaxValue);
    sqlCmd.Parameters["@XMLDATA"].Direction = ParameterDirection.Input;
    sqlCmd.Parameters["@XMLDATA"].Value = xml;

    sqlCmd.ExecuteScalar();
    sqlCmd.Connection.Close();
    sqlCmd.Connection.Dispose();
}   

在这种特定情况下,spr_Sync_Customer是存储过程。在存储过程中,XML 数据使用 Xquery 进行解析,并执行相应的insert/update/delete操作。

图:使用 Xquery 解析 XML

在这种特定情况下,@XMLDATA是为提供的 XML 准备的存储过程输入参数。解析 XML,您可以根据需要使用解析后的数据填充数据库表,在此示例中,我填充了Customer表。

结论

上面给出的示例非常基础,旨在为使用 Xquery 进行 CRUD 提供一个基本的入门。您可以使用该概念来处理更复杂的想法,为了获得更好的性能,请尽可能在 XML 数据类型上使用exist()方法。如果您想了解更多关于 Xquery 的知识,可以在这里找到非常有用的指南。示例源代码包含在本文中,您可以根据需要自由修改。

历史

  • 版本 1.0 @2010 年 11 月 30 日
© . All rights reserved.