C# 如何从SQL中读取父数据和子数据?

C# 如何从SQL中读取父数据和子数据?,c#,asp.net,sql,sql-server-2008,ado.net,C#,Asp.net,Sql,Sql Server 2008,Ado.net,再次感谢您发布的所有精彩答案 我有两个SQL表。第一个定义父级,并有一个名为ParentId的主键列。我还有一个子表,它有一个主键和一个外键作为“ParentId”。因此,这两个表构成了单亲到多个子关系 问题是拉取父+子数据C代码的最有效方法是什么?必须将数据读入以下对象: public class Parent { public int ParentId { get; set; } public List<Child> Children { get; set; }

再次感谢您发布的所有精彩答案

我有两个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 ... //
}
使用这种方法,我必须找到所有唯一的父行,然后读取所有的子行。优点是我只去db一次

第二个版本是分别阅读所有家长:

SELECT * FROM Parents
SELECT * FROM Children
然后分别阅读所有儿童:

SELECT * FROM Parents
SELECT * FROM Children
并使用LINQ将所有家长与孩子合并。该方法可向db发送两次数据

第三种也是最后一种也是最低效的方法是抓取所有父对象,在构造每个父对象时,访问DB以抓取其所有子对象。这种方法需要n+1个连接:1个连接用于所有家长,n个访问次数用于获取每个家长的所有孩子

有没有关于如何更容易做到这一点的建议?当然,我不能不使用存储过程,也不能使用LINQ2SQL或EF。您更喜欢数据表还是数据读取器?如果是,如何使用方法1或方法2

谢谢,
马丁

我通常在餐桌上做这个决定。有些桌子我经常需要孩子们,所以我马上就去拿。在其他情况下,访问孩子是很少见的,所以我懒得加载他们

我猜选项2在带宽方面比选项1更有效,因为您没有重复任何数据

您可以在一个存储过程中同时执行这两个查询,并使用sqldataadapter(即新的SqlDataAdaptercommand.FillmyDataSet)通过代码执行该过程,其中myDataSet将包含两个表

从这里,您可以阅读第一个表,通过ParentId在字典中创建父字典,然后只需阅读第二个表中的每一行即可添加子字典:

parents[(int)myDataSet.Tables[1]["ParentId"]].Children.Add(new Child() { etc } );
伪代码可能有点不对劲,但希望您能大致了解一下

使用这种方法,我必须找到 所有唯一的父行,然后 读所有的孩子


您可以通过p.ParentId包含订单。这确保来自同一父级的所有子级都在连续的行中。因此,您可以读取下一行,如果父对象已更改,则创建新的父对象,否则将子对象添加到上一个父对象。无需搜索唯一的父行。

我更喜欢在一个查询中提取所有结果,只需在一个循环中构建树

    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
      }
    }

我显然需要孩子们,这就是为什么我首先要问这个问题。