再次感谢您发布的所有精彩答案!
我在SQL中有两个表。第一个定义父项,并具有名为ParentId的主键列。我还有一个子表,它有一个主键,一个外键有'ParentId'。因此,这两个表形成了一个父母 - 与许多孩子的关系。
问题是提取父+子数据C#代码的最有效方法是什么?必须将数据读入以下对象:
public class Parent
{
public int ParentId { get; set; }
public List<Child> Children { get; set; }
// ... many more properties ... //
}
public class Child
{
public int ChildId { get; set; }
public string Description { get; set; }
// ... many more properties ... //
}
如果我使用以下查询,我将立即获得父母和子女,其中每个父母将重复多少子女的次数:
SELECT
p.ParentId as 'ParentId',
c.ChildId as 'ChildId',
-- other relevant fields --
FROM
Parents p
INNER JOIN
Children c
ON
p.ParentId = c.ParentId
使用这种方法我必须找到所有唯一的父行,然后读取所有的子行。优点是我只进行了一次db。
第二个版本是分别阅读所有家长:
SELECT * FROM Parents
然后分别阅读所有孩子:
SELECT * FROM Children
并使用LINQ将所有父母与孩子合并。这种方法可以两次前往数据库。
第三种也是最后一种(也是最低效的)方法是抓住所有父母,并在构建每个父对象时,前往数据库抓住所有的孩子。这种方法需要n + 1个连接:所有父母都有1个连接,每个父母都有n次旅行以获得所有孩子。
有关如何更轻松地提出建议吗?当然,我无法摆脱使用存储过程,我不能使用LINQ2SQL或EF。您更喜欢数据表与数据读取器,如果是这样,如何使用方法1或2?
谢谢, 马丁
答案 0 :(得分:2)
我更喜欢在一个查询中提取所有结果,只需在一个循环中构建树
SELECT p.ParentId as 'ParentId', null as 'ChildId'
FROM Parents p
UNION ALL
SELECT c.ParentId as 'ParentId', c.ChildId as 'ChildId'
FROM Children c
List<Parent> result = new List<Parent>();
Parent current;
while (dr.Read())
{
if (string.isNullOrEmpty(dr['ChildId']))
{
//create and initialize your parent object here and set to current
}
else if (!string.isNullOrEmpty(dr['ChildId'])
&& dr['ParentId'].ToString().Equals(current.ParentId.ToString())
{
//create and initialize child
//add child to parents child collection
}
}
答案 1 :(得分:1)
使用这种方法我必须找到 所有唯一的父行,然后 读了所有的孩子。
您可以添加order by p.ParentId
。这可确保来自同一父级的所有子级都在连续的行中。因此,您可以读取下一行,如果父项已更改,则创建新的父对象,否则将子项添加到上一个父项。无需搜索唯一的父行。
答案 2 :(得分:0)
我通常在表级做出这个决定。有些桌子我经常需要孩子,所以我马上抓住它们。在其他情况下,访问孩子是罕见的,所以我懒惰他们。
答案 3 :(得分:0)
我认为选项#2对选项#1的带宽更有效(因为你不重复任何数据)。
您可以在一个存储过程中同时拥有这两个查询,并使用sqldataadapter(即(new SqlDataAdapter(command)).Fill(myDataSet)
执行该过程,其中myDataSet
将包含这两个表。)
从那里你读了第一个表,通过ParentId创建父母的字典(在Dictionary<int, Parent>
中),然后只需读取第二个表中的每一行来添加子项:
parents[(int)myDataSet.Tables[1]["ParentId"]].Children.Add(new Child() { etc } );
伪代码可能有点偏差,但希望你能得到一般的想法