惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

M
MIT News - Artificial intelligence
雷峰网
雷峰网
OSCHINA 社区最新新闻
OSCHINA 社区最新新闻
Last Week in AI
Last Week in AI
奇客Solidot–传递最新科技情报
奇客Solidot–传递最新科技情报
阮一峰的网络日志
阮一峰的网络日志
月光博客
月光博客
博客园 - Franky
腾讯CDC
T
Tailwind CSS Blog
Recent Announcements
Recent Announcements
V
V2EX
N
Netflix TechBlog - Medium
量子位
Jina AI
Jina AI
Y
Y Combinator Blog
The GitHub Blog
The GitHub Blog
G
Google Developers Blog
爱范儿
爱范儿
博客园 - 叶小钗
D
Docker
MongoDB | Blog
MongoDB | Blog
D
DataBreaches.Net
T
The Blog of Author Tim Ferriss

博客园 - AndrewCheng

即时查看程序输出的VS插件 让.Net验证控件与自定义验证合作无间 把你的应用程序添加到IE工具栏 - AndrewCheng - 博客园 拦截并分发运行时动态创建控件的事件 程序设计中的调试方法总结 从SQL Server 数据库转换为Access注意事项 昆明喷码机耗材科技有限公司 软件版本后缀所代表的含义 论坛网址 工作格言 加密 web.config - AndrewCheng - 博客园 C#正则表达式 - AndrewCheng - 博客园 论坛等级分类 - AndrewCheng - 博客园 SQL Server和Oracle的常用函数对比 屏蔽IE浏览器javasccipt的方法 VS2005断开VSS后再次连接上VSS时注意事项 asp.net2.0页面按钮点击无效的解决办法 delegate与event示例程序 C#实现的正余玄函数图象
TableAdapter和多组数据结果
AndrewCheng · 2009-01-02 · via 博客园 - AndrewCheng

     很多人问我TableAdapter是否能够从存储过程里读取多组数据结果。最直接的回答是:不能。你不能通过TableAdapter.Fill()方法来得到一个Dataset。但是我们可以通过另一种简单的方法来实现。

DataAdapter.Fill()和多组数据结果

     TableAdapter.Fill()方法通过调用DataAdapter.Fill()从数据库中读取数据。DataSet.Fill() 方法可以从存储过程里读取多组数据结果。为了获得多组数据结果,可以应用DataAdapter.Fill()的一个重载方法,它将Dataset作为参数,这样就可以把存储过程的多组数据结果返回给包含有多个表的Dataset

    这里,我们通过一个简单的示例来演示一下这种方法是怎样实现的:

    假设在Northwind数据库里有一个存储过程dbo.spSelectCustomersOrders

    CREATE PROCEDURE spSelectCustomersOrders
    AS
    BEGIN 
       SET NOCOUNT ON
       SELECT * FROM Customers 
       SELECT * FROM Orders
    END
   GO

     下面的代码调用了这个存储过程,并且把2组数据结果存储在Dataset里。

    Dim myConn As New System.Data.SqlClient.SqlConnection
    Dim myAdapter As New System.Data.SqlClient.SqlDataAdapter
    Dim mySelectCommand As New System.Data.SqlClient.SqlCommand
    Dim myDataset As New System.Data.DataSet

    myConn.ConnectionString = "Data Source=.\SQLExpress;Initial Catalog=Northwind;Integrated       Security=True"
    mySelectCommand.Connection = myConn
    mySelectCommand.CommandText = "dbo.spSelectCustomersOrders"
    myAdapter.SelectCommand = mySelectCommand
    myAdapter.Fill(myDataset)

    For Each table As System.Data.DataTable In myDataset.Tables
       Console.WriteLine("Table Name:" & table.TableName)
    Next

    代码的输出形式如下:

     Table Name: Table
     Table Name: Table1

     我们可以看到,DataAdapter.Fill()方法执行了存储过程,并且把2组数据结果分别存储在2个数据表里。

TableAdapter的解决方案

     然而,为什么TableAdapter.Fill()方法不能够正确地处理多组数据结果?那是因为TableAdapter.Fill()调用的DataAdapter.Fill()方法是以DataTable作为参数,而不是Dataset。这种情况,我们只需要在TableAdapter里创建一个新的Fill方法,令其调用以Dataset为参数的DataAdapter.Fill()方法。

     假设这里有一个包含CustomersOrdersNorthwindDataset.xsd文件。让我们用上面的存储过程来实现新的Fill方法。把下面的代码加到partial class文件里。(在Dataset Designer上,可以通过双击或者右键选择"View Code"来进入partial class,当然也可以手动创建一个空的class文件。)

    Namespace NorthwindDataSetTableAdapters
        Partial Public Class CustomersTableAdapter
            Public Function FillCustomersOrders(ByVal dataSet As NorthwindDataSet) As Integer 
                 Dim
multiSelectCommand As New System.Data.SqlClient.SqlCommand 
                 Dim returnValue As Integer multiSelectCommand.Connection = Me.Connection 
                 multiSelectCommand.CommandText = "dbo.spSelectCustomersOrders" 
                 Me
.Adapter.SelectCommand = multiSelectCommand 
                 '' Map auto-created Table1 that holds the second result-set (Orders rows) to 
                 '' Orders DataTable in our Dataset. 
                 Me.Adapter.TableMappings.Add("Table1", "Orders"
                returnValue = Me.Adapter.Fill(dataSet) 

                Return
returnValue 
            End Function 
         End
Class
     End
Namespace

      有两点需要特别注意:

      首先,新的FillCustomersOrders是以Dataset为参数,这样当我们调用DataAdapter.Fill()方法时,数据结果就会准确地存储到Dataset里。

      第二,注意我们是怎样应用TableMapping将自动生成的数据表映射到Dataset里的Orders表。当应用DataAdapter.Fill()来读取多组数据结果,每一组数据结果都被单独地存储在Dataset的数据表里。默认情况下,这些数据表被命名为Table, Table1, Table2…,为了将这些数据标与Dataset里定义的数据表相对应,我们应用TableMapping。如果你打开NorthwindDataset.xsd后面的代码,在TableAdapter classInitAdapter()方法,你就会看到类似的代码:

    tableMapping.SourceTable = "Table"
    tableMapping.DataSetTable = "Customers"
    '' Colum mapping code skipped
     ...
     Me._adapter.TableMappings.Add(tableMapping)

      这段代码是为了保证DataAdapter.Fill方法返回的数据表与Dataset里的数据表相对应。在我们FillCustomersOrders示例里,第二组结果包含的是Orders信息,所以我们在Table1Orders之间创建了映射关系,确保数据FillOrders表中。

     把以上代码添加到partial class后,你就可以调用FillCustomersOrders方法来fill CustomersOrders

     CustomersTableAdapter.FillCustomersOrders(Me.NorthwindDataSet)

性能的考虑

      有些情况下,这种方法的确很有效。但是这也要看情况,也许你会想到这个方法可以避免多次访问数据库,从而提高性能,但如果仅仅只需要获取一小部分数据,却应用这种方法一次读取了大量的数据,这同样也会降低性能,倒不如一次读取小部分数据,需要其它数据时,与数据库建立另一个连接,再读取。ADO.NET在处理多个数据库连接方面性能优化得还是不错的,很多情况下,都不至于导致性能瓶颈。总之我们只需要遵循最基本的原则:只在需要的时候,才去读取数据。

     但有些情况下,读取多组数据结果还是很有帮助的,所以,应用我在这里所介绍的方法吧,但时刻也不要忘记性能的问题。

相关资源