将对象保存到数据库的良好做法 [关闭]

Posted

技术标签:

【中文标题】将对象保存到数据库的良好做法 [关闭]【英文标题】:good practice for saving objects to database [closed] 【发布时间】:2012-09-06 00:33:45 【问题描述】:

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

我知道的大致有三种方式

    在服务器端创建即席 SQL 查询(似乎更慢 + 更脆弱,如果您更改服务器端语言,则必须重新创建所有这些代码)

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

    使用某种 ORM 技术(我知道有些人对此深信不疑,但我们宁愿避免使用它,因为我们没有足够的经验来准确判断它是否是我们想要走的路,并且有足够多的关于性能问题和复杂性的讨论,考虑到其他一切都在发生,采用 KISS 理念,我们在承诺它时有点紧张)

我想知道的是:

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

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

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

编辑: 感谢大家的回复。即使这已经关闭,我也会做出回应(仍然不清楚为什么在 *** 上禁止讨论)。抱歉耽搁了一段时间。

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

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

但是感谢您的回复;只是想看看是否还有其他我们可能错过的方法。看起来 ORM 是值得花一些时间在一边的。

再次感谢。

-马辛

【问题讨论】:

XML 变体很有趣,对于新项目,我们在单独的 C# 项目中有业务逻辑,我们计划有 SaveAggregateEntity 过程,它将接受表属性作为输入,然后在过程中我们将执行合并与聚合实体相关的每个数据库表的语句。我很好奇这种方法将如何发挥作用。 【参考方案1】:

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

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

关于使用 XML 作为存储过程的参数,Erland Sommarskog 提供了一些 great material 关于如何处理此问题的选项,包括 XML。他对 OPENXML 也有以下要说的

在 SQL 2000 中,由于 OPENXML 功能,您可以使用 XML。 OPENXML 在 SQL 2005 和 SQL 2008 中仍然存在,但大约是唯一的 使用它的原因是您还需要支持 SQL 2000。 OPENXML 使用起来比较笨重,而且性能远不及节点。在 事实上,在我的测试中,它比迭代方法慢 30-50%。一 不过,OPENXML 可能的优势是查询计划是 更简单。 XQuery 的查询计划将 XML 运算符与关系运算符混合在一起 运算符,而 OPENXML 只产生一次远程扫描。这 降低您有时遇到的查询计划灾难的风险 XQuery。

Martin Fowler 在OrmHate 上也有一篇很棒的文章,它很好地讨论了人们不愿使用 ORM 框架背后的一些原因。他以建议结束他的文章;

所以 ORM 帮助我们处理大多数企业的一个非常现实的问题 应用程序。确实,它们经常被滥用,有时 可以避免潜在的问题。它们不是漂亮的工具,但是 他们解决的问题也不是很可爱。我觉得他们 应该得到更多的尊重和更多的理解。

我认为在你的情况下,这是非常合适的,因为它们确实需要相当长的时间来掌握。

因此,我更倾向于选择选项 2 (XML),并首先考虑以 XML 的构造方式合并您想要的顺序,或者看看结合节点和 SQL Server 的 ROW_NUMBER 函数。

【讨论】:

【参考方案2】:

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

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

我确实认为 NoSQL(RavenDB 等)对于您的场景值得考虑。

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

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

【讨论】:

【参考方案3】:

我们在两个项目中非常成功地使用了以下内容:

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

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

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

CRUD 方法非常快,因为您不必创建或解析任何 XML,并且程序可以准确地处理手头的情况。数据库之类的。由于程序往往很小,因此也很容易发现错误。

在您的情况下,我认为序列化和反序列化 XML 没有用。无论如何,您都需要本机 DB-Client/Driver,它可以很好地处理传递不同类型的多个字段。您的 Web 服务器代码最终会干净地调用 DB,而 DB 不需要处理解析 XML,这不是它的主要工作。

【讨论】:

以上是关于将对象保存到数据库的良好做法 [关闭]的主要内容,如果未能解决你的问题,请参考以下文章

将对象从数组保存到数据库[关闭]

用于保存数据的良好 Python 模块 [关闭]

REST API 错误返回良好做法 [关闭]

在 Blazor 中将值从子组件传递到父页面的良好做法?

如何使用PHP / MySQL实现良好的MVC模式而不会丢失SQL请求时间/服务器内存? (良好做法)

在班级中保存文件或频道的良好做法