C# 为返回多个表的存储过程创建强类型数据集

C# 为返回多个表的存储过程创建强类型数据集,c#,database,dataset,strongly-typed-dataset,C#,Database,Dataset,Strongly Typed Dataset,我有一个执行3选择的存储过程。如何创建能够访问所有3个表并读取数据的强类型数据集。默认情况下,VisualStudio仅使用第一个表生成数据集 我已经尝试使用VisualStudio类型化数据集拖放存储过程 存储过程如下所示: Create Procedure GetData As Begin Select ColA, ColB, ColC from TableA Select ColD, ColE, ColF from TableB Select ColG, ColH, ColI from T

我有一个执行3选择的存储过程。如何创建能够访问所有3个表并读取数据的强类型数据集。默认情况下,VisualStudio仅使用第一个表生成数据集

我已经尝试使用VisualStudio类型化数据集拖放存储过程

存储过程如下所示:

Create Procedure GetData
As
Begin
Select ColA, ColB, ColC from TableA
Select ColD, ColE, ColF from TableB
Select ColG, ColH, ColI from TableC
End

如果您不顾一切地想这样做,我认为您不会成功地使用纯强类型设计器生成的解决方案;tableadapters用于在db数据的本地datatable表示(强类型datatable)和返回行的数据库查询之间进行调解。tableadapter中的“表”与数据表相关,而不是与数据库表相关

单个tableadapter不打算在3个本地datatables和提供3个数据库查询输出的远程过程之间充当中介。基本上,它无法做到这一点,因为没有任何客户端代码可以用来识别您的sql of

Select ColA, ColB, ColC from TableA
Select ColD, ColE, ColF from TableB
Select ColG, ColH, ColI from TableC
…来自
select*from TableA
的结果应该放在您的数据集中的tableadatable中,等等。来自TableA的数据在传输过程中丢失,因为它完全不相关,甚至可能不真实

当tableadapter与单个select一起正确使用时,它隐式地知道结果应该放在哪个datatable中。TableAdatable有一个对应的TableDataableAdapter,TableDataableAdapter从数据库中的某个位置选择数据并将其存储在TableAdatable中-在数据集中TableDataAdapter没有设计用于操作的其他表,因此它不需要任何关于数据块在运行查询后的位置的提示。TableATableAdapter甚至可以加载一个查询,该查询根本不会从数据库TableA返回任何数据;只要运行的查询生成一组数字和类型正确的列,这些数据就会进入TableAdatable,因为TableDataAdapter是硬编码的。它不为其他数据表服务,并且对任何其他数据表都不感兴趣

因为您的存储过程无法向tableadapter指示哪些结果集应存储在哪个表中,所以您所设想的解决方案无法工作

简单的规则是:“一只狗,一个完成”-“一个db查询结果集,一个tableadapter,一个强类型datatable”

因此,我坚决建议您按照预期使用这些东西:

  • 为TableA、TableB和TableC创建3个TableAdapter和相应的datatables
  • 在代码中分别填写以下各项:


“我们希望避免在一个页面上调用多个db”并没有真正的意义——这听起来像是解决了您想象的问题,而不是真正发生的问题。尝试一次而不是三次执行这些操作,几乎没有什么性能优势。你可能不同意,但要检验一下——不要只是凭直觉。连接是池化的,语句是缓存和准备的,如果您真的认为这会有很大帮助,那么可以同时执行3条语句

在一天结束时,如果你有9兆字节的数据要从数据库中取出,那么每次3次3兆的数据取出与每次1次9兆的数据取出的区别将是微不足道的;您不需要等待30秒来打开连接,一秒钟读取3MB,再等待30秒来关闭连接,也不需要重新进行连接(总时间为183秒),也不需要将所有瓶颈归因于连接管理。即使您确实有一个超级延迟连接,该连接需要30秒来传输SELECT,再需要30秒来开始读取数据,您也可以同时启动3个请求,根据定义,发送3个SELECT所需的时间与调用1个过程调用所需的时间相同(两者都需要61秒)


如果你不能同意尝试一次完成所有工作的理由是虚假的,那么你可能希望继续尝试通过你选择的方法来完成,在这种情况下,我认为你必须选择:

使用标准的dataadapter和dataset 然后将数据移动到类型集中以使用它

SqlConnection con = new SqlConnection("YourConnection String");
SqlDataAdapter da = new SqlDataAdapter();
DataSet ds = new DataSet();
SqlCommand cmd = new SqlCommand("storedprocedure", con);
cmd.CommandType = CommandType.StoredProcedure;
cmd.Parameters.AddWithValue("@p1", whatever); //if you have parameters.
SqlDataAdapter da= new SqlDataAdapter(cmd);
da.Fill(ds);
con.Close();
现在您有了一个包含3个表的数据集,您的问题是确定哪个表是哪个表。假设ds.Tables[0]用于TableA:

foreach(var ro in ds.Tables[0].Rows)
  typedDs.TableA.AddTableARow(ro.ItemArray);
对b和c表重复此步骤

将3个查询转换为1个查询 您的示例似乎表明所有3个表都具有相同的列数。如果列的类型也相同,则可以合并查询,并将其加载到单个表适配器中,然后将其填充到单个强类型数据表中。然后,您可能需要做更多的工作,将它们拆分为单独的数据表。也许修改查询以返回列,以便跟踪数据的来源:

Select 'tableA' as wherefrom, ColA, ColB, ColC from TableA
UNION ALL
Select 'tableB' as wherefrom, ColD, ColE, ColF from TableB
UNION ALL
Select 'tableC' as wherefrom, ColG, ColH, ColI from TableC
这是一个混乱,一个麻烦,一个黑客



为什么这么难?好。。引用另一句老话:如果很难,你就做错了。TableAdapter是以X方式设计的,而您正试图以Y方式使用它们。退一步,看看你为什么这么做背后的原因——这才是真正的问题所在

如果你不顾一切地想这么做,我认为用纯强类型设计器生成的解决方案是不会成功的;tableadapters用于在db数据的本地datatable表示(强类型datatable)和返回行的数据库查询之间进行调解。tableadapter中的“表”与数据表相关,而不是与数据库表相关

单个tableadapter不打算在3个本地datatables和提供3个数据库查询输出的远程过程之间充当中介。基本上,它无法做到这一点,因为没有任何客户端代码可以用来识别您的sql of

Select ColA, ColB, ColC from TableA
Select ColD, ColE, ColF from TableB
Select ColG, ColH, ColI from TableC
…假设
select*from table a
的结果为