【问题标题】:How do I return multiple result sets with SqlCommand?如何使用 SqlCommand 返回多个结果集?
【发布时间】:2012-10-03 19:38:37
【问题描述】:

我可以执行多个查询并只执行一次SqlCommand 就返回它们的结果吗?

【问题讨论】:

  • 多个 SELECT 查询?还是插入/更新?如果查询是 SELECT,它们是否返回具有相同布局的数据?拜托,这个问题太模糊了。
  • 多个 SELECT 查询,都具有相同的布局。我不能使用 UNION,因为我有一些 T-SQL 逻辑阻止我这样做。

标签: c# sql-server ado.net


【解决方案1】:

SqlDataReader.NextResult(调用SqlCommand.ExecuteReader返回一个SqlDataReader):

在读取批处理 Transact-SQL 语句的结果时,将数据读取器推进到下一个结果 [集]。

例子:

string commandText = @"SELECT Id, ContactId
FROM dbo.Subscriptions;

SELECT Id, [Name]
FROM dbo.Contacts;";


List<Subscription> subscriptions = new List<Subscription>();
List<Contact> contacts = new List<Contact>();

using (SqlConnection dbConnection = new SqlConnection(@"Data Source=server;Database=database;Integrated Security=true;"))
{
    dbConnection.Open();
    using (SqlCommand dbCommand = dbConnection.CreateCommand())
    {
        dbCommand.CommandText = commandText;
        using(SqlDataReader reader = dbCommand.ExecuteReader())
        {
            while(reader.Read())
            {
                subscriptions.Add(new Subscription()
                {
                    Id = (int)reader["Id"],
                    ContactId = (int)reader["ContactId"]
                });
            }

            // this advances to the next resultset 
            reader.NextResult();

            while(reader.Read())
            {
                contacts.Add(new Contact()
                {
                    Id = (int)reader["Id"],
                    Name = (string)reader["Name"]
                });
            }
        }
    }
}

其他例子:

【讨论】:

  • 这正是我想要的。谢谢!
【解决方案2】:

创建一个有多个选择的Stored Procedure,并填充DataSet

using (SqlConnection conn = new SqlConnection(connection))
{
    DataSet dataset = new DataSet();
    SqlDataAdapter adapter = new SqlDataAdapter();
    adapter.SelectCommand = new SqlCommand("MyProcedure", conn);
    adapter.SelectCommand.CommandType = CommandType.StoredProcedure;
    adapter.Fill(dataset);
    return dataset;
}

对于存储过程中的每个选择,返回的数据集的 Tables 数组中都会有一个 DataTable

【讨论】:

  • +1 因为这是“更简单的方法”;但是,它不一定是存储过程 - 批处理中的多个语句 应该 可以正常工作 IIRC。
  • 我相信你是对的,我只是不记得了。我知道它适用于存储过程。
【解决方案3】:

“dapper”之类的工具让这一切变得非常简单,无论您使用的是临时文本查询还是存储过程;例如:

using(var multi = conn.QueryMultiple(sql, args))
{
    var customers = multi.Read<Customer>().AsList(); // first grid
    var regionName = multi.ReadFirstOrDefault<string>(); // second grid
    var addresses = multi.Read<Address>().AsList(); // third grid
    // todo: use those things
}

也可以通过Read[&lt;T&gt;] 的可选参数读取单个网格而无需缓冲(作为阅读器本身的打开IEnumerable&lt;T&gt;)。

【讨论】:

    【解决方案4】:

    我调用一个 sproc 并获得多个带有对象的结果集,所以你最终得到一个

    List<List<Dictionary<string, object>>>
    

    在 multiResultsSet 中,每个结果集都是那么

    List<Dictionary<string, object>>
    

    他们可以是cast to their types 并根据需要转换为模型。

    在你设置好所有需要的 sproc 命令后,将它传递给这个:

        private static List<List<Dictionary<string, object>>> ProcessReader(SqlCommand command)
        {
            var tables = new List<List<Dictionary<string, object>>>();
            using (var reader = command.ExecuteReader())
            {
                do
                {
                    var table = new List<Dictionary<string, object>>();
                    while (reader.Read())
                        table.Add(Read(reader));
                    tables.Add(table);
                } while (reader.NextResult());
            }
            return tables;
        }
    

    并且 Read() 相当简单。

        private static Dictionary<string, object> Read(IDataRecord reader)
        {
            var row = new Dictionary<string, object>();
            for (var i = 0; i < reader.FieldCount; i++)
            {
                var val = reader[i];
                row[reader.GetName(i)] = val == DBNull.Value ? null : val;
            }
            return row;
        }
    

    【讨论】:

      【解决方案5】:

      我正在使用字典方法。 您可以使用 Newton Json 将其转换为 json。 这样你就不会被类型和 IDataRecord 所束缚

      public List<List<Dictionary<string, object>>> ExecuteSqlReader(string cmd, int commandTimeout = 30, CommandType commandType = CommandType.Text)
              {
                 var sqlCmd = new SqlCommand(cmd);
                 var allRecord = new List<List<Dictionary<string, object>>>();
                  using (var connection = GetSqlConnection(commandTimeout, commandType, ref sqlCmd))
                  {
                      using (var reader = sqlCmd.ExecuteReader())
                      {
                          if (reader.HasRows)
                          {
                              var result = new List<Dictionary<string, object>>();
                              while (reader.Read())
                              {
                                  result = GetTableRowData(reader);
                              }
      
                              allRecord.Add(result);
                          }
                          while (reader.NextResult())
                          {
                              if (reader.HasRows)
                              {
                                  var result = new List<Dictionary<string, object>>();
                                  while (reader.Read())
                                  {
                                      result = GetTableRowData(reader);
                                  }
                                  allRecord.Add(result);
                              }
                          }
                      }
                  }
                  return allRecord;
              }
      

      【讨论】:

        【解决方案6】:

        这是我用来返回多个结果集的方法。

        public abstract class BaseRepo
        {
            private string _connectionString;
        
            protected BaseRepo(string connectionString)
            {
                _connectionString = connectionString;
            }
        
            private SqlConnection GetSqlConnection(int commandTimeout, CommandType commandType, ref SqlCommand sqlCmd)
            {
                var connection = new SqlConnection(_connectionString);
                connection.Open();
                sqlCmd.Connection = connection;
                sqlCmd.CommandTimeout = commandTimeout;
                sqlCmd.CommandType = commandType;
                return connection;
            }
        
            protected int ExecuteSql(SqlCommand sqlCmd, int commandTimeout = 30, CommandType commandType = CommandType.Text)
            {
                using (var connection = GetSqlConnection(commandTimeout, commandType, ref sqlCmd))
                {
                    return sqlCmd.ExecuteNonQuery();
                }
            }
        
            protected IEnumerable<T> ExecuteSqlReader<T>(Func<IDataRecord, T> CreateObject, SqlCommand sqlCmd, int commandTimeout = 30, CommandType commandType = CommandType.Text)
            {
                using (var connection = GetSqlConnection(commandTimeout, commandType, ref sqlCmd))
                {
                    using (var reader = sqlCmd.ExecuteReader())
                        return ExecuteReader(CreateObject, reader);
                }
            }
        
            protected Tuple<IEnumerable<T1>, IEnumerable<T2>> ExecuteSqlReader<T1,T2>(Func<IDataRecord, T1> CreateObject1, Func<IDataRecord, T2> CreateObject2,  SqlCommand sqlCmd, int commandTimeout = 30, CommandType commandType = CommandType.Text)
            {
                using (var connection = GetSqlConnection(commandTimeout, commandType, ref sqlCmd))
                {
                    using (var reader = sqlCmd.ExecuteReader())
                    {
                        var result1 = ExecuteReader(CreateObject1, reader).ToList();
                        var result2 = ExecuteReader(CreateObject2, reader).ToList();
                        return Tuple.Create<IEnumerable<T1>, IEnumerable<T2>>(result1, result2);
                    }
                }
            }
        
            protected Tuple<IEnumerable<T1>, IEnumerable<T2>, IEnumerable<T3>> ExecuteSqlReader<T1, T2, T3>(Func<IDataRecord, T1> CreateObject1, Func<IDataRecord, T2> CreateObject2, Func<IDataRecord, T3> CreateObject3, SqlCommand sqlCmd, int commandTimeout = 30, CommandType commandType = CommandType.Text)
            {
                using (var connection = GetSqlConnection(commandTimeout, commandType, ref sqlCmd))
                {
                    using (var reader = sqlCmd.ExecuteReader())
                    {
                        var result1 = ExecuteReader(CreateObject1, reader).ToList();
                        var result2 = ExecuteReader(CreateObject2, reader).ToList();
                        var result3 = ExecuteReader(CreateObject3, reader).ToList();
                        return Tuple.Create<IEnumerable<T1>, IEnumerable<T2>, IEnumerable<T3>>(result1, result2, result3);
                    }
                }
            }
        
            protected Tuple<IEnumerable<T1>, IEnumerable<T2>, IEnumerable<T3>, IEnumerable<T4>> ExecuteSqlReader<T1, T2, T3, T4>(Func<IDataRecord, T1> CreateObject1, Func<IDataRecord, T2> CreateObject2, Func<IDataRecord, T3> CreateObject3, Func<IDataRecord, T4> CreateObject4, SqlCommand sqlCmd, int commandTimeout = 30, CommandType commandType = CommandType.Text)
            {
                using (var connection = GetSqlConnection(commandTimeout, commandType, ref sqlCmd))
                {
                    using (var reader = sqlCmd.ExecuteReader())
                    {
                        var result1 = ExecuteReader(CreateObject1, reader).ToList();
                        var result2 = ExecuteReader(CreateObject2, reader).ToList();
                        var result3 = ExecuteReader(CreateObject3, reader).ToList();
                        var result4 = ExecuteReader(CreateObject4, reader).ToList();
                        return Tuple.Create<IEnumerable<T1>, IEnumerable<T2>, IEnumerable<T3>, IEnumerable<T4>>(result1, result2, result3, result4);
                    }
                }
            }
        
            private IEnumerable<T> ExecuteReader<T>(Func<IDataRecord, T> CreateObject, SqlDataReader reader)
            {
                while (reader.Read())
                {
                    yield return CreateObject(reader);
                }
                reader.NextResult();
            }
        }
        

        然后我就这样继承它:

        public class ReviewRepo : BaseRepo
        {
            public ReviewRepo(string connectionString) : base(connectionString) { }
        
            public ReviewPageableResult GetAllReviews(string productType, string serviceType, int pageNumber, int itemsPerPage, string sortBy, string sortDirection)
            {
                var parameters = new List<SqlParameter>
                {
                    new SqlParameter("ProductRefDescription", productType),
                    new SqlParameter("ServiceRefDescription", serviceType),
                    new SqlParameter("ZipCodes", "NULL"),
                    new SqlParameter("PageNumber", pageNumber),
                    new SqlParameter("ItemsPerPage", itemsPerPage),
                    new SqlParameter("SortBy", sortBy),
                    new SqlParameter("SortDirection", sortDirection)
                };
                var cmd = new SqlCommand("dbo.GetReviews");
                cmd.Parameters.AddRange(parameters.ToArray());
                var results = ExecuteSqlReader(CreateReview, CreateReviewPageableResult, cmd, commandType: CommandType.StoredProcedure);
                var reviewResult = results.Item2.Single();
                reviewResult.Items = results.Item1;
                return reviewResult;
            }
        
            public ReviewPageableResult GetReviewsByZip(string productType, string serviceType, string zipCodes, int pageNumber, int itemsPerPage, string sortBy, string sortDirection)
            {
                var parameters = new List<SqlParameter>
                {
                    new SqlParameter("ProductRefDescription", productType),
                    new SqlParameter("ServiceRefDescription", serviceType),
                    new SqlParameter("ZipCodes", zipCodes),
                    new SqlParameter("PageNumber", pageNumber),
                    new SqlParameter("ItemsPerPage", itemsPerPage),
                    new SqlParameter("SortBy", sortBy),
                    new SqlParameter("SortDirection", sortDirection)
                };
                var cmd = new SqlCommand("dbo.GetReviewsByZipCodes");
                cmd.Parameters.AddRange(parameters.ToArray());
                var results = ExecuteSqlReader(CreateReview, CreateReviewPageableResult, cmd, commandType: CommandType.StoredProcedure);
                var reviewResult = results.Item2.Single();
                reviewResult.Items = results.Item1;
                return reviewResult;
            }
        
            private Review CreateReview(IDataRecord record)
            {
                return new Review
                {
                    PageReviewId = (int)record["PageReviewId"],
                    ProductRefId = (Guid)record["ProductRefId"],
                    ServiceTypeRefId = Convert.IsDBNull(record["ServiceTypeRefId"]) ? Guid.Empty : (Guid)record["ServiceTypeRefId"],
                    TerritoryId = Convert.IsDBNull(record["TerritoryId"]) ? Guid.Empty : (Guid)record["TerritoryId"],
                    FirstName = $"{record["FirstName"]}",
                    LastName = $"{record["LastName"]}",
                    City = $"{record["City"]}",
                    State = $"{record["State"]}",
                    Answer = $"{record["Answer"]}",
                    Rating =(double)record["Rating"],
                    SurveyDate = (DateTime)record["SurveyDate"]
                };
            }
        
            private ReviewPageableResult CreateReviewPageableResult(IDataRecord record)
            {
                return new ReviewPageableResult
                {
                    AverageRating = (double)record["AverageRating"],
                    Count1Stars = (int)record["Count1Stars"],
                    Count2Stars = (int)record["Count2Stars"],
                    Count3Stars = (int)record["Count3Stars"],
                    Count4Stars = (int)record["Count4Stars"],
                    Count5Stars = (int)record["Count5Stars"],
                    ItemsPerPage = (int)record["ItemsPerPage"],
                    PageNumber = (int)record["PageNumber"],
                    TotalCount = (int)record["TotalCount"],
                };
            }
        }
        

        【讨论】:

        • 我可以看到很多代码是从一些专有解决方案中复制出来的,最终产生了 user166390 的想法
        • 从来没有说过我写的。这是我所见过的东西的融合,加上我的一些东西,让它们一起工作。
        【解决方案7】:

        试试这个

        Dim dt1, dt2, dt3As New DataTable
            Dim command As SqlCommand
            Dim adapter As New SqlDataAdapter
            Dim ds As New DataSet
            Dim Sql1, Sql2, Sql3 As String
        
            Sql1 = "select id, CurName from Table1 where IS_Deleted=0 order by id"
            Sql2 = "select id ,Item from Table2 order by id"
            Sql3 = "select id ,SellPrice from Table3 order by id"
        
            Try
        
                conn1.Open()
                command = New SqlCommand(Sql1, conn1)
                command.CommandType = CommandType.Text
                adapter.SelectCommand = command
                adapter.Fill(ds, "dt1")
        
                adapter.SelectCommand.CommandText = Sql2
                adapter.Fill(ds, "dt2")
        
                adapter.SelectCommand.CommandText = Sql3
                adapter.Fill(ds, "dt3")
        
        
                adapter.Dispose()
                command.Dispose()
                conn1.Close()
        
        
                cmbCurrency.DataSource = ds.Tables("dt1") 
                cmbCurrency.DisplayMember = "CurName"
                cmbCurrency.ValueMember = "id"
                cmbCurrency.SelectedIndex = -1 
                '''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''|
        
                cmbGroups.DataSource = ds.Tables("dt2") 
                cmbGroups.DisplayMember = "Item"                                    
                cmbGroups.ValueMember = "id"                                        
                cmbGroups.SelectedIndex = -1                                        
                '''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''|
        
                cmbUnits.DataSource = ds.Tables("dt3")  
                cmbUnits.DisplayMember = "SellPrice" 
                cmbUnits.ValueMember = "id" 
                cmbUnits.SelectedIndex = -1                                         
                '''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''|
        
            Catch ex As Exception
               MessageBox.Show(ex.ToString())
            End Try
        

        更多帮助http://vb.net-informations.com/dataset/dataset-multiple-tables-sqlserver.htm

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2013-08-23
          • 1970-01-01
          • 1970-01-01
          • 2016-06-14
          • 1970-01-01
          相关资源
          最近更新 更多