在 C# 中的泛型 FillDataSet 方法中映射强类型数据集

本文关键字:映射 强类型 方法 数据集 泛型 FillDataSet | 更新日期: 2023-09-27 17:48:52

编辑:我正在使用SqlDataAdapters来填充数据集。对不起——我应该更清楚。

我正在从事一个项目,我需要用来自存储过程的信息填充许多强类型数据集。现在,我的数据访问层中有一个通用方法:

public static DataSet FillDataSet(DataSet dataSet, string storedProcedureName, Dictionary<string, string> parameters);

这样做的问题是,我需要在存储过程返回的记录集和数据集中的表之间建立映射。我想出了两个选项:

  • 向我的FillDataSet方法(KeyValuePair<string, string>[] mappings(添加新的形式化,它将为表映射提供信息。
  • 创建一个将数据集作为参数的DataSetMappingFactory,然后根据其类型添加适当的映射。如果它是未知类型,则不会添加任何映射。然后,它将DataSet返回到 FillDataSet 方法。

你们中有人对我如何处理这个问题有其他想法吗?另外,有没有人想权衡一种在面向对象设计方面最好的方法?

在 C# 中的泛型 FillDataSet 方法中映射强类型数据集

我要问的第一个问题是:我真的需要这样做吗? 类型化数据集设计器已为您提供了一个工具,用于定义存储过程和数据表之间的映射。 如果您谨慎地设计数据集,则每个数据表都已有一个 Fill 方法。 重新发明那个轮子有意义吗?

我认为可能。 有一种方法可以维护该映射,这真的很酷,但是该映射中的所有内容在编译时都会冻结。 如果要更改映射,则需要重新生成程序集。 此外,类型化数据集设计不处理返回多个结果集的存储过程。 如果要以常规方式映射参数和值,则必须使用反射从 Fill 方法获取参数列表。 如果您查看这些因素(以及我没有想到的其他因素(,使用现有工具可能不是要走的路。

在这种情况下,在我看来,您的目标是能够使用尽可能少地了解实现细节的代码从一系列存储过程中填充 DataSet。 所以这是一个由元数据驱动的过程。 当您有一个由元数据驱动的流程时,从长远来看,对您来说最重要的是维护流程使用的元数据的难易程度。 一旦你让代码工作,你可能不会经常接触它。 但是您将不断调整元数据。

如果我从这个角度看问题,我想做的第一件事就是设计一个类型化的数据集来包含元数据。 这给了我们一堆我们必须弄清楚的事情:

  • 持久性格式
  • 构建绑定 UI 的简单途径
  • 如果我们
  • 决定走这条路,那么将元数据持久化在数据库中的一条同样简单的途径
  • 用于导航数据的对象模型。

在此数据集中,您将有一个 DataSetType 表,该表键入您打算能够填充的每个类型化数据集的类型。 它将有一个子存储过程表,每个被调用的 SP 都有一行。 这将有两个子表,参数和数据表类型。 对于 SP 预期返回的每个结果集,将有一个按序号位置排序的 DataTableType 行。 数据表类型表将具有子列映射表。 在该表中,您将维护结果集中的列与要填充的表中的列之间的映射。

确保所有数据关系都是嵌套的,并且已为关系指定了合理的名称。 (我喜欢FK_childtablename_parenttablename

一旦你有了这个,类设计就变得非常简单。 该类具有对元数据 DataSet、Connection 等的引用,它公开了一个具有此签名的方法:

public void FillDataSet(DataSet targetDs, Dictionary<string, Dictionary<string, KeyValuePair<string, string>> parameterMap);

首先使用 targetD 的"类型"查找顶级数据集类型行。 然后,所有私有方法都遍历 DataTable.GetChildRows(( 返回的 DataRows 列表。 并且向类设计中添加一两个事件,以便在它执行操作时可以引发事件,让调用应用程序知道它的进度。

也许我希望重构这个设计的第一个地方是让我对填充过程进行更精细的控制。 例如,按照设计,每个类型化数据集只有一组 SP。 如果我只想填充数据集的子集,该怎么办? 按照设计,我不能。 但是,您可以轻松地将 DataSetType 表的主键分为两部分,其中部分是数据集类型和一些字符串键(名称如 SPSetName 或 OperationName(,并将键的第二部分添加到 FillDataSet 参数列表中。