将一对多关系从数据库服务器传递到客户端的最佳(更干净,资源更少)方法是什么?
想象一下,我有一个Author表和一个Book表。我想要检索名称以“a”开头的所有作者以及他们写的所有书籍。然后,在客户端生成一个对象数组“作者”,其“书籍”字段是一组对象“书籍”。
我想到的两个穷人解决方案是:
第一个解决方案实际上是数据库方面的密集型(如果我有1000个作者,我必须执行1001个查询)。
第二个需要在客户端进行一些密集的工作,因为程序会解析结果,因为它具有每行重复的Author共同的数据。
另一种解决方案是从存储过程返回多个记录集。我从来没有处理过多个记录集,我不确定所有的语言/适配器类都支持它们。
当然,如果任何作者可以拥有书籍和论文,并且每本书都可以有样本页面等,情况会变得更糟。
有什么想法吗? 感谢
编辑: 我正在使用.net,所以ado的datarelations是一个选项。他们支持我的oracle和mysql吗?
答案 0 :(得分:2)
这里有两个问题。一个是如何最有效地收集数据,另一个是如何处理您收到的数据。
首先如何收集它:
SELECT a.* FROM Author a INNER JOIN Book b ON a.id=b.author_id WHERE left(a.name,1)='a'
喜欢非常昂贵,如果可以,请避免使用它。内连接是比较表最便宜的方法 - 特别是如果主键(id)和外键(author_id)上有索引 如果有作者没有书籍(我猜不会是作者),请使用LEFT JOIN(相同的语法只需将'inner'改为'left')
二。如果你正在谈论1000条记录,你可能会想到以两个单独的方式收集数据(比如你认为的第一选择),除非你希望用户永远等待页面加载。例如:用户选择以a开头并收到列表的所有作者 - 你甚至可以统计该作者的文章。
SELECT a.Name count(b.author_id) titles
FROM Author a INNER JOIN Book b ON a.id=b.author_id
WHERE left(a.name,1)='a'
GROUP BY a.Name
他们会看到
John Adam: 35 Titles
Jane Acaba: 18 Titles
Jim Allan: 3 Titles
然后,用户点击作者,加载该作者的书籍列表。
Jim Allan's Titles:
Froggy went a court'n
Death on the Nile
Life in Africa
如果你希望它看起来像是完全一次拉,但你希望它快速过来使用xmlhttp或ajax来显示作者列表。这是另一个主题。 :)
我还应该补充说,存储过程是必须的。这将大大增加应用程序的可移植性以及大多数数据库的性能。
HTH
答案 1 :(得分:0)
我认为后者可能比前者更接近一个好的解决方案。
也就是说,您可能希望在客户端和数据库之间引入一个层 - 在数据库机器上 - 可以过滤并处理从DB到您选择的数据结构的行。
答案 2 :(得分:0)
这可能取决于RDBMS的选择,其中一些可能支持某些功能,可以启用您想要的功能,尽管该功能可能无法移植到另一个RDBMS。
例如,Microsoft SQL Server从SQL 2000开始支持SELECT FOR XML。当仔细精心制作XML模式(例如FOR XML EXPLICIT)时,这将完全符合您的要求 - 返回一个XML,它为您提供数据的层次结构。如果您还使用ADO.NET,并选择使用SqlDataAdaptor将其加载到DataSet中,则结果DataSet实际上已将所有数据设置到DataTable中,并在DataTable之间设置正确的DataRelations。但是,这可能是特定于MS-SQL的功能,而在另一个RDBMS中工作可能需要一些其他技术。
答案 3 :(得分:0)
我们使用多个记录集。如果您有另一个实体链接到作者,只需添加另一个记录集。不确定Oracle和MySQL,但是如果IDataReader的相应实现让NextResult()没有抛出NotSupportedException,那么这应该适用于它们。
答案 4 :(得分:0)
假设一个典型案例,您的数据量将主要位于“图书”表中。采用最简单的解决方案,对于您希望对用户造成的任何显示大小,惩罚较小 - 将两者连接在一起并返回单个行集,其中“Authors”列数据中包含一定量的冗余。其他解决方案需要多个查询,在整个方案中,在大多数情况下,这些查询都更加昂贵和复杂。
我的优先顺序通常是:提供最佳用户界面体验所需的内容,为最简单的实施而构建(通常的免责声明指出了不寻常的设计)。
这也可能最好地将您的数据策略与UI设计中的更改分离,因为所有内容都在一个易于导航的结果集中。