programing

SqlCommand를 사용하여 여러 결과 집합을 반환하려면 어떻게 해야 합니까?

closeapi 2023. 6. 30. 22:22
반응형

SqlCommand를 사용하여 여러 결과 집합을 반환하려면 어떻게 해야 합니까?

여러 쿼리를 실행하고 다음을 실행하여 결과를 반환할 수 있습니까?SqlCommand딱 한 번?

SqlDataReader를 참조하십시오.NextResult(SqlCommand 호출 시 SqlDataReader가 반환됨)ExecuteReader):

배치 Transact-SQL 문의 결과를 읽을 때 데이터 판독기를 다음 결과 [set]로 진행합니다.

예:

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"]
                });
            }
        }
    }
}

다른 예:

작성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;
}

반환된 데이터 집합에는 다음이 포함됩니다.DataTable저장 프로시저의 각 선택 항목에 대한 테이블 배열입니다.

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

개별 그리드도 버퍼링 없이 읽을 수 있습니다(개방형으로).IEnumerable<T>선택적 매개 변수를 통해 (판독기 자체를 통해)Read[<T>].

저는 사전적인 접근법을 사용하고 있습니다.Newton Json을 사용하여 Json으로 변환할 수 있습니다.이렇게 하면 유형 및 ID 데이터 레코드에 얽매이지 않습니다.

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

저장 프로시저를 호출하고 개체가 포함된 여러 결과 집합을 가져오므로 다음과 같이 됩니다.

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

multiResultsSet에서 각 결과 세트는 다음과 같습니다.

List<Dictionary<string, object>>

필요에 따라 유형에 맞게 주조하고 모델로 변환할 수 있습니다.

필요한 모든 항목을 포함하여 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;
    }

읽기()는 매우 간단합니다.

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

이것은 제가 여러 결과 세트를 반환하는 데 사용해 온 것입니다.

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"],
        };
    }
}

사용해 보세요.

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

Use QueryMultiple of IDbConnection Interface -

 using (var connection = OpenConnection())
            {
                var result = connection.QueryMultiple("sqlStoredProcedure",new
                {
                    Id = item.Id,
                   
                }, commandTimeout: 3600
                , commandType: CommandType.StoredProcedure);

                res1 = result.Read<T>().ToList();
                res2 = result.Read<T>().ToList();
            }

언급URL : https://stackoverflow.com/questions/12715620/how-do-i-return-multiple-result-sets-with-sqlcommand

반응형