数据库结构略有不同的多客户项目的架构设计(针对每个客户)
我正在维护一个为每个新客户复制粘贴的应用程序(...是的,我知道)。如果一个新客户想要一些其他人不需要的新功能,则只需更改他的代码部分即可。该解决方案还包括一种“common.dll”,其中放置的所有代码对于所有客户都是相同的。
每个客户的底层 MSSQL 数据库略有不同。所有表都或多或少具有相同的表,但有些客户具有用于自定义特定功能的附加列或新表等。
由于每个客户的 Visual Studio 解决方案中都使用“类型化数据集”(ADO.NET C# 2.0),因此始终有一个特定的解决方案(文件)以及其中的特定类型数据集(例如“XyDataSet.xsd”)。在解决方案中,我有辅助类,例如。用于处理订单。此类中的方法之一可以是“GetOrder(string orderId)”,它使用客户特定的数据集来检索订单(如键入的 DataRow)。
正如您所看到的,我在每个客户的每个解决方案中都有“GetOrder”方法,因为订单表中可能会有一些差异,例如可能有附加列。因此,如果需要对一般的“GetOrder”功能进行更改,我必须在所有项目中更改它,这当然是维护的噩梦。
你们中有人看到可以改进这种“架构”的方法吗?或者也许当前底层的不同数据库方案在更高的应用程序级别上没有太多需要改进的地方?
I'm maintaining an application that was copy-pasted for each new customer (...yeah, I know). If a new customer wanted some new functions which the others didn't need, only his code part was changed. The Solution also includes a sort of "common.dll" where all code is put that is the same for all customers.
The underlying MSSQL database for each customer is slightly different. All have more or less the same tables but some customers have for example additional columns or new tables for the custom specific functions.
As "typed datasets" (ADO.NET C# 2.0) are used in the Visual Studio solution for each customer there is always a specific solution (file) and in it a specific typed dataset (eg. "XyDataSet.xsd"). In the solutions I have helper classes eg. for handling orders. One of the methods in this class could be "GetOrder(string orderId)" which uses the customer specific DataSet to retrive an order (as typed DataRow).
As you see I have "GetOrder" methods in each solution for each customer as there might be little differences in the order table like maybe additional columns. So if a change is needed to the general "GetOrder" functionality I have to change it in all projects which is of course a maintenance nightmare.
Do anybody of you see a way in which this "architecture" could be improved? Or maybe with the currently underlying different DB schemes there isn't much to improve in the higher application level?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
完全回答这个问题非常困难,但我会开始这样思考:
数据库级别:
找到什么是加法,并将其放在单独的表中,指示该表中哪个(来自公共模式)是该行及其相应值的所有者。例如
订单 {OrderID、CustomerID 等}(这是所有者表)
OrderExtensions {ExtensionID, ExtensionName, ExtensionValue}(这是订单的扩展表)
OrderExtensionsToCustomers {CustomerID, ExtensionID}(这显示哪个扩展可用于哪个客户)
数据访问层级别:
领域模型层级别:
UI层级别:
最终图:
我知道这是一个很长的答案,但我希望这是有道理的:-)
It is very difficult to answer this question completely, but I would start thinking this way:
Database level:
Find what is addition and have that in separate tables, indicating in that table which (from common schema) is the owner of the row and its corresponding value. e.g.
Orders {OrderID, CustomerID, etc.} (this is owner table)
OrderExtensions {ExtensionID, ExtensionName, ExtensionValue} (this is extension table for Orders)
OrderExtensionsToCustomers {CustomerID, ExtensionID} (this shows which extension is available for which customer)
Data-access-layer level:
Domain-model layer level:
UI layer level:
Final picture:
I know it is a long answer, but I hope this makes sense :-)
使用一种返回非类型化数据集的通用方法(在共享程序集中或在服务中)怎么样?然后,您可以在每个解决方案中使用方法,将该方法返回的数据放入类型化数据集中。这样您就可以将与数据库交互的逻辑保留在一个地方。
What about using one common method (in a shared assembly or in a service) that is returning untyped dataset? Then you can have methods in each solution that puts the data returned from this method into typed datasets. That way you can keep the logic for interacting with the database in one place.
首先,哎哟。艰难的演出。
您可以做很多事情来迁移到更好的架构 - 这有点取决于您可以花多少时间在上面。我建议阅读 Kerievsky 的“重构模式”以获取想法。
为了回答您的具体问题 - 我会考虑“模板方法”模式。一般来说,您将 getOrder 定义为一系列步骤,并允许子类根据需要覆盖这些步骤。
http://www.dofactory.com/Patterns/PatternTemplate.aspx
我同意 Ole您需要做的事情之一就是整理返回类型 - 这将使重构时变得更加容易。
如果您还没有这样做,我还建议您投资单元测试。
Firstly, ouch. Tough gig.
There are lots of things you could do to move to a better architecture - it kinda depends on how much time you are allowed to spend on it. I'd suggest reading "Refactoring to Patterns" by Kerievsky for ideas.
To answer your specific question - I'd consider the "template method" pattern. Broadly speaking, you define getOrder as a series of steps, and allow subclasses to override those steps as required.
http://www.dofactory.com/Patterns/PatternTemplate.aspx
I agree with Ole that one of the things you will need to do is sort out the return types - that will make life a lot easier when it comes to refactoring.
I'd also suggest investing in unit tests if you haven't already done so.
创建一个类型化数据集,其中包含表的所有公共列,但不包含专用列。在每个表的相应 xsd 文件中添加一个
这将允许将未在 xsd 数据集中定义的列加载到数据表中。
可以通过类型化数据集访问公共列,可以通过其名称访问客户特定列,或者您可以创建
自定义特定的扩展方法来获取附加列。
我不确定 vs2008/vs2010 数据集编辑器是否可以处理这个问题,甚至破坏
anyAttribute
信息。但 dotnet xsd.exe 代码生成器支持anyAttribute
自 dotnet 1.0 以来,包括当前的 dotnet 4.0Create a typed dataset that contains all common colums of the tables but not the specialised ones. In the corresponding xsd-file for each table addd a
This will allow to load columns into a datatable that are not defined in the xsd-dataset.
The common colums can be accessed via the typed dataset, the customer specific colums can be accessed through their name or you can create
custom specific extension-methods to get the additional colums.
I am not shure if vs2008/vs2010 dataset-editor can handle this or even destroys the
anyAttribute
information. But the dotnet xsd.exe codegenerator supportsanyAttribute
since dotnet 1.0 including current dotnet 4.0