【问题标题】:Mapping strongly-typed DataSets in a generic FillDataSet method in C#?在 C# 中的通用 FillDataSet 方法中映射强类型数据集?
【发布时间】:2008-10-23 17:39:40
【问题描述】:

编辑:我正在使用 SqlDataAdapters 来填充数据集。抱歉——我应该更清楚一点。

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

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

问题是我需要在存储过程返回的记录集和我的数据集中的表之间建立映射。为此,我提出了两种选择:

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

对于我如何解决这个问题,你们还有其他想法吗?另外,是否有人想权衡一种在面向对象设计方面最好的方法?

【问题讨论】:

  • 您使用什么机制来填充各种数据表?数据阅读器?表适配器?还有什么?
  • 我正在使用 SqlDataAdapters。我已经更新了问题以明确这一点。 :)

标签: c# sql oop n-tier-architecture


【解决方案1】:

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

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

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

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

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

在此 DataSet 中,您将有一个 DataSetType 表,以您打算能够填充的每个类型化 DataSet 的类型为键。它将有一个子 StoredProcedures 表,每个被调用的 SP 都有一行。那将有两个子表,Parameter 和 DataTableType。对于 SP 预期返回的每个结果集,将有一个 DataTableType 行,按序号位置排序。 DataTableType 表将有一个子 ColumnMapping 表。您将在该表中维护结果集中的列与您正在填充的表中的列之间的映射。

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

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

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

您首先使用 targetDs 的 Type 来查找顶级 DataSetType 行。然后所有私有方法遍历 DataTable.GetChildRows() 返回的 DataRows 列表。然后在类设计中添加一两个事件,这样当它执行操作时,它可以引发事件,让调用应用程序知道它是如何进行的。

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

【讨论】:

  • 这是解决我的问题的一种非常有趣的方法。我不确定是否会使用它,因为它会给我的项目增加开销,但我喜欢这些信息将由数据集驱动。
  • 如果您必须保留元数据,并且/或者您希望能够在不重新构建/重新部署软件的情况下对其进行修改,那么开销突然看起来非常小。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-03-22
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多