将对象保存到数据库的良好实践

时间:2012-09-06 00:33:45

标签: sql-server xml stored-procedures maintenance

最近我们一直想知道人们发现什么能够很好地将业务对象/实体保存到数据库中。出于讨论的目的,请考虑订单中包含一些项目的示例(客户详细信息,名称,数量,价格等)。我们正在使用SQL Server和C#,并为旧项目使用一些传统的ASP Classic / Jscript,没有机会转向NoSQL类型的解决方案等。

我知道的方法大致有三种

  1. 在服务器端创建adhoc SQL查询(看起来更慢+更脆弱,如果更改服务器端语言,则必须重新创建所有这些代码)

  2. 使用接受订单的XML表示的存储过程,然后存储过程将读取文档并执行任何需要完成的操作。 (这是我们到目前为止使用的方法)

  3. 使用某种ORM技术(我知道有些人会发誓,但我们宁愿避免它,因为我们没有足够的经验来准确衡量它是否是我们想要的路径对于性能问题和复杂性有足够的喋喋不休,我们有点紧张,因为其他事情正在进行,采用KISS理念)

  4. 我想知道的是:

    1. 是否有人有任何其他/更好的方法不在我们可以调查的上述列表中

    2. XML方法是否是标准/良好实践。我们喜欢它,因为大多数语言都支持序列化为XML,它是Web友好的,在调试过程中易于阅读,而且非常灵活(易于扩展,可以通过模式选择强弱等),但希望有机会考虑其他想法。

    3. 注意:Using OPENXML in SQL Server 2008 stored proc - INSERT order differs from XML document似乎在某些方面具有相关性;到目前为止我们已经使用了openxml()所以我想要问的问题是,如果XML方法是一种合理的方法,XQuery是一种更好的方法吗?是否有一个方便的参考/帖子,有人可以指出在灵活性,可读性等方面以这种方式做事的最佳方式。

      编辑: 感谢大家的回复。即使已经关闭,我也会做出我的回复(仍然不清楚为什么在StackOverflow上讨论是禁止的)。道歉需要一段时间。

      我应该澄清一下;我们发现XML有用的地方是我们有一个由几个较小的业务对象组成的“复杂”对象。例如,带有“项目”的订单;可能有一个或多个项目。如果我们加载订单然后用户将一个项目添加到他们的订单中,我们只需添加另一个项目,序列化为XML然后将其传递给存储过程,该存储过程可以判断它是插入还是更新,而我不是确定你将如何做到这一点(除了我要避免的很多小存储过程/ adhoc SQL.ORMs:见下面的评论)。如果我们处理一些相当于行的插入/更新的扁平结构,那么具有强类型参数的常规存储过程效果很好。

      关于ORM的其他评论;我发现Martin Fowler对这件作品的链接很有趣。我已经阅读了原版http://blogs.tedneward.com/2006/06/26/The+Vietnam+Of+Computer+Science.aspx,但我总是欣赏更多信息。我目前对ORM的主要关注只是学习使用它的复杂性,并且使用它很好(避免陷阱等),这给我们正在处理的当前环境看起来有点多处理。

      但感谢回复;只是想看看是否还有其他我们可能错过的方法。看起来ORM是一些值得投资的东西。

      再次感谢。

      -Marcin

3 个答案:

答案 0 :(得分:1)

听起来您可能希望在数据库(即存储过程)中保留业务逻辑和相当多的应用程序,以便可以从多个编程环境中重用它?如果是这种情况,我想我可以将XML发送到存储过程。

我的正常偏见完全相反,更喜欢在任何使用.NET 2.0或更高版本的项目中使用NHibernate。使用ORM有一个学习曲线,但是你可以大大提高开发人员的工作效率和相当多的强类型,而且在最近的.NET版本中你也可以获得Linq。

我认为NoSQL(RavenDB等)值得考虑你的场景。

就性能而言,动态SQL和ORM很可能让您非常接近存储过程性能,并且通常有必要在必要时更接近金属。我会更关心解析XML的性能,这通常很慢。解析XML也很脆弱。

在您的情况下,我可能会主张将任何与数据库通信的应用程序移动到最新版本的.NET并将业务逻辑移出数据库层。从长远来看,这可能比继续处理您正在处理的零碎环境的总维护成本更低。我知道尽管如此说服管理层是多么困难。

答案 1 :(得分:1)

我们使用以下两个项目非常成功:

每个业务对象在数据库中获取一个或多个存储过程,用于创建/更新/删除它。 (有时称为“CRUD”)该过程将前端/ Web服务器与数据库结构完全隔离。

是的,您必须为每个对象编写这些对象(有一些工具可以生成它们的基本版本,例如Management Studio的SSMS-Tools),是的,您必须为每个新字段扩展这些对象。但是,如果使用XML来传输数据,则还必须更改当前的XML解析过程。使用XML,您可以避免更改过程的签名,但这有点像作弊,因为您传输DID的数据结构发生了变化。您只是将其隐藏在XML中。

在前端/ Web服务器端,您必须为所有业务对象提供一种保存方法,然后只调用相关过程并将所有字段传递给它。如果使用命名参数,您也可以独立于参数的顺序,并且可以省略可选参数,这使您可以扩展过程而无需更改对它的每次调用。

CRUD方法非常快,因为您不必进行任何XML创建或解析,并且这些过程可以完全处理手头的情况。这样的数据库。它也使得查找错误变得容易,因为程序往往很小。

我认为在您的案例中序列化和反序列化XML没有用处。无论如何,您需要本机DB-Client / Driver,它可以很好地处理不同类型的多个字段。您的Web服务器代码最终会对数据库进行干净调用,并且数据库不需要处理解析XML,这不是主要工作。

答案 2 :(得分:1)

我需要更详细地说明您在对象方面保存到SQL Server的确切内容,但如果您只是将XML作为业务对象的表示保存到数据库,那么我建议您没有充分利用关系数据库。

设计良好的数据库可以通过约束,通过外键引用完整性来帮助实施业务规则,并提供许多其他好处,如果您只是将XML存储在给定的表中,则可能会遗漏这些好处。

关于使用XML作为存储过程的参数,Erland Sommarskog有一些关于如何处理这个问题的great material选项,包括XML。他还有关于OPENXML的以下内容

  

由于OPENXML功能,您已经可以在SQL 2000中使用XML了。   OPENXML仍然在SQL 2005和SQL 2008中,但仅限于此   使用它的原因是你需要支持SQL 2000。   OPENXML使用起来比较庞大,并且性能远不及节点。在   事实上,在我的测试中,它比迭代方法慢30-50%。一   但是,OPENXML的可能优势在于查询计划是   简单。 XQuery的查询计划将XML运算符与关系混合在一起   运算符,而OPENXML只能进行一次单独的远程扫描。这个   降低您有时会遇到的查询计划灾难的风险   的XQuery。

Martin Fowler也有一篇关于OrmHate的精彩文章,它提供了一个非常好的讨论,讨论了人们不愿意使用ORM框架背后的一些原因。他通过暗示结束他的文章;

  

因此,ORM帮助我们处理大多数企业的非常现实的问题   应用。确实,他们经常被误用,有时甚至被滥用   可以避免潜在的问题。它们不是漂亮的工具,但随后   他们解决的问题也不是完全可爱的。我觉得他们   值得更多的尊重和更多的理解。

我认为在你的情况下,这是非常合适的,因为他们需要花费相当多的时间来掌握。

因此,我更倾向于倾向于选项2(XML),并且首先考虑以XML构造的方式合并您所需的顺序,或者考虑结合使用XML的可能性。节点和SQL Server的ROW_NUMBER函数。