多客户项目的架构设计,具有不同的数据库结构(针对每个客户)

时间:2011-03-15 09:47:38

标签: .net ado.net dataset strongly-typed-dataset architecture

我正在维护一个为每个新客户复制粘贴的应用程序( ...是的,我知道)。如果新客户想要一些其他人不需要的新功能,那么他的代码部分只会被更改。该解决方案还包括一种“common.dll”,其中所有代码的放置对所有客户都是相同的。

每个客户的基础MSSQL数据库略有不同。所有表都有或多或少相同的表,但有些客户具有自定义特定功能的附加列或新表。

由于“类型化数据集”(ADO.NET C#2.0)在Visual Studio解决方案中用于每个客户,因此始终存在特定的解决方案(文件),并且其中包含特定类型的数据集(例如“XyDataSet.xsd”) 。在解决方案中,我有帮助类,例如。处理订单。此类中的一个方法可能是“GetOrder(string orderId)”,它使用客户特定的DataSet来检索订单(作为类型化的DataRow)。

如您所见,我为每个客户在每个解决方案中都有“GetOrder”方法,因为订单表中可能没有太多差异,例如可能有其他列。因此,如果需要对一般的“GetOrder”功能进行更改,我必须在所有项目中进行更改,这当然是维护噩梦。

你们有没有人看到这种“架构”可以改进的方式?或者,对于当前潜在的不同数据库方案,在更高的应用程序级别上没有太大的改进?

4 个答案:

答案 0 :(得分:3)

完全回答这个问题非常困难,但我会开始这样思考:

数据库级别:

  • 查找常见内容并将其作为数据库架构。
  • 查找添加内容并在单独的表中具有该内容,在该表中指示哪些(来自公共模式)是该行的所有者及其对应的值。 e.g。

    订单{OrderID,CustomerID等}(这是所有者表)
    OrderExtensions {ExtensionID,ExtensionName,ExtensionValue}(这是订单的扩展表)
    OrderExtensionsToCustomers {CustomerID,ExtensionID}(显示哪个扩展程序适用于哪个客户)

数据访问层级:

  • 应在此处实施数据库级设计。

域模型层级:

  • 一些带有功能的操作(对于UI图层)应该移到这里。

UI图层级:

  • 从这里开始应该将一些东西移到数据库层,例如仅针对某些客户显示的UI元素,将其视为仅为特定客户激活的“功能”(扩展名),因此仅对他们可见。
  • 就个人而言,我会通过抽象“特征”术语来进一步,使其可动态加载。如果您习惯使用反射,这很容易实现。如果可以实现这一点,那么它将为您提供在域层中拥有一些代码的特权 - 并非所有客户的所有代码放在一起,而是在需要时根据请求动态加载特定客户。

最终图片:

  • 客户访问UI界面,实际上是特定页面。
  • 查询数据库以查找当前客户可用的UI功能(例如其他按钮等)。
  • 数据库返回客户每个功能的定义。
  • 每个要素都会动态加载并添加到页面中(例如,添加到要素的特殊占位符)。
  • 当功能需要采取行动时,它会将请求传递给域层,域层又会为功能加载“处理器”部分,也可以动态加载,或者只是找到需要调用的功能实现。
  • 呼叫被路由到数据库,公共信息被保存到公共(所有者)表,而其他(扩展)信息被保存到其他(扩展)表。

我知道这是一个很长的答案,但我希望这是有道理的: - )

答案 1 :(得分:1)

使用返回无类型数据集的一种常见方法(在共享程序集或服务中)怎么样?然后,您可以在每个解决方案中使用将此方法返回的数据放入类型化数据集的方法。这样,您就可以在一个地方保持与数据库交互的逻辑。

答案 2 :(得分:1)

首先,哎哟。艰难的演出。

你可以做很多事情来建立一个更好的架构 - 这有点取决于你可以花多少时间花在它上面。我建议您阅读Kerievsky的“重构模式”以获取创意。

要回答您的具体问题 - 我会考虑“模板方法”模式。一般来说,您将getOrder定义为一系列步骤,并允许子类根据需要覆盖这些步骤。 http://www.dofactory.com/Patterns/PatternTemplate.aspx

我同意Ole的观点,你需要做的事情之一是理清返回类型 - 这将使重构时的生活变得更加容易。

如果您还没有这样做,我还建议您投资单元测试。

答案 3 :(得分:1)

创建一个类型化数据集,其中包含表的所有常用列,但不包含专用列。在每个表的相应xsd文件中添加一个

  <xs:anyAttribute />

这将允许将列加载到未在xsd-dataset中定义的数据表中。

可以通过类型化数据集访问常用列,可以通过名称访问客户特定列,也可以创建 获取额外列的自定义特定扩展方法。

如果vs2008 / vs2010数据集编辑器可以处理这个问题甚至破坏anyAttribute信息,我不会感到害羞。但dotnet xsd.exe代码生成器支持anyAttribute,因为dotnet 1.0包括当前的dotnet 4.0