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

时间:2019-06-20 12:05:09

标签: c# database dataset strongly-typed-dataset

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

我已经尝试使用Visual Studio的Typed Dataset拖放存储过程。

存储过程如下:

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

1 个答案:

答案 0 :(得分:0)

如果您急于这样做,那么我认为采用纯粹的强类型设计器生成的解决方案不会成功。 tableadapters旨在在db数据的本地数据表表示形式(您的强类型数据表)和返回行的数据库查询之间进行中介。 tableadapter中的“表”与数据表相关,与数据库表无关。

单个tableadapter不能用作3个本地数据表和提供3个数据库查询输出的远程过程之间的中介。基本上它无法执行此操作,因为对于您的sql,客户端代码无法使用任何东西来识别...

Select ColA, ColB, ColC from TableA
Select ColD, ColE, ColF from TableB
Select ColG, ColH, ColI from TableC

...应该将select * from TableA的结果放入数据集中的TableADataTable等中。从tableA出来的数据在有线传输中会丢失,因为它完全不相关,并且可能甚至都不是真的。

当一个tableadapter正确地用于一次选择时,它隐式知道应该将结果放入数据表。TableADataTable有一个对应的TableATableAdapter,并且TableATableAdapter从db中的某个位置选择数据并将其存储在TableADataTable中- TableATableAdapter旨在处理数据集中的其他表,因此它不需要任何有关数据块在运行查询后的位置的提示。 TableATableAdapter甚至可以加载一个查询,该查询根本不从数据库TableA返回任何数据。只要它运行的查询产生一组具有正确编号和类型的列,该数据就会进入TableADataTable中,因为TableATableAdapter是硬编码的。它不提供其他任何数据表,并且对其他任何数据表都不感兴趣。

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

简单的规则是:“一只狗,一个完成”-“一个数据库查询结果集,一个表适配器,一个强类型数据表”

因此,我强烈建议您按预期使用这些东西:

  • 为TableA,TableB和TableC创建3个表适配器和相应的数据表
  • 在代码中分别填写每个人:

var ds = new StronglyTypedDataSet();
var ata as new TableATableAdapter();
ata.Fill(ds);
var bta as new TableBTableAdapter();
bta.Fill(ds);
var cta as new TableCTableAdapter();
cta.Fill(ds);

“我们希望避免对单个页面进行多次数据库调用”实际上没有任何意义-听起来像是解决了您想象中的问题,而不是真的解决。尝试一次执行而不是3次执行这些事情,几乎没有性能优势。您可能会不同意,但请对其进行测试-不要只是凭直觉。连接被池化,语句被缓存并准备好,如果您真的认为这将极大地帮助您,则可以同时执行3条语句。

在一天结束时,如果您要从数据库中提取9兆字节的数据,那么这样做的区别就在于每3 mb 3 mb的3次拉取与9次1的拉取之间的差异将很小。您并不需要等待30秒才能打开连接,每秒读取3 mb,等待另外30秒才能关闭广告,而必须重新做一次(总时间为183秒),并且所有瓶颈都归因于连接管理。即使您 did 具有超延迟连接,该连接将花费30秒来传输SELECT,另外30秒才能开始读取数据,您也可以同时启动3个请求,并且根据定义,这将花费相同的时间发送3个SELECT,因为它将调用1个过程调用(均耗时61秒)


如果您不同意一次尝试全部操作的原因是虚假的,那么您不妨继续尝试通过选择的方法进行操作,在这种情况下,我认为您将不得不选择: / p>

使用标准的数据适配器和数据集

,然后将数据移入类型集以进行处理

SqlConnection con = new SqlConnection("YourConnection String");
SqlDataAdapter da = new SqlDataAdapter();
DataSet ds = new DataSet();
SqlCommand cmd = new SqlCommand("sproc", 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方式使用它们。退后一步,查看执行此操作的原因-这才是真正的问题所在