Как клонировать данные из SqlDataReader, сохраняя все столбцы и строки таким образом, чтобы их можно было экспортировать с помощью метода? - PullRequest
1 голос
/ 25 апреля 2019

В настоящее время я пытаюсь создать метод, который позволяет мне выполнять любой запрос на строке соединения и получать результаты, возвращаемые читабельным способом для моего веб-сайта ASP.Net.Поскольку мне нужен доступ ко всем строкам и столбцам, которые могут понадобиться в запросе, я не могу просто вернуть строку или массив строк.Если я верну SqlDataReader, я не смогу прочитать данные вне метода, потому что соединение закрыто.

Вот так выглядит мой метод в настоящее время.

private SqlDataReader QueryConnectionString (string query)
    {
        // New SQL Connection
        SqlConnection cnn;

        // New Connection String
        string connetionString = ConfigurationManager.ConnectionStrings["ConnectionStringName"].ConnectionString;

        // Instantiate the SQL Connection with Connection String
        cnn = new SqlConnection(connetionString);

        // Create a SqlCommand with the input Query
        SqlCommand command = new SqlCommand(query, cnn);

        cnn.Open();

        // Create a SqlDataReader and tie it to the query
        SqlDataReader reader = command.ExecuteReader();        

        cnn.Close();

        return reader;
    }

В других моих методах у меня было бы что-то вроде этого

SqlDataReader reader = QueryConnectionString("SELECT * FROM tTable");

lblOutput.Text = reader.GetString(0);

Но при этом я получаю ошибку

System.InvalidOperationException: 'Недопустимая попытка вызова CheckDataIsReady, когда читатель закрыт.'

Я понимаю, что возвращение SqlDataReader не вариант.Что я могу вернуть данные так, чтобы другие методы могли читать данные?

Ответы [ 2 ]

2 голосов
/ 25 апреля 2019

Вы можете попробовать это

IEnumerable<IDataRecord> GetRecords()
{
    using(var connection = new SqlConnection(@"..."))
    {
        connection.Open();

        using(var command = new SqlCommand(@"...", connection);
        {
            using(var reader = command.ExecuteReader())
            {
               while(reader.Read())
               {
                   // your code here.
                   yield return reader;
               }
            }
        }
    }
}
1 голос
/ 25 апреля 2019

Вы можете вернуть DataTable, который сохранит столбцы и строки запроса. Вместо SqlDataReader рассмотрите возможность использования SqlDataAdapter. Одним из преимуществ является то, что Fill метод SqlDataAdapter откроет и закроет соединение для вас.

var dt = new DataTable();    
using (var da = new SqlDataAdapter(query, cnn))
{      
    da.Fill(dt);
}

Ваш полный метод может выглядеть примерно так:

private DataTable GetData(string query)
{
    // New Connection String
    string connetionString = ConfigurationManager.ConnectionStrings["ConnectionStringName"].ConnectionString;

    // Instantiate the SQL Connection with Connection String
    SqlConnection cnn = new SqlConnection(connetionString);

    // declare datatable
    var dt = new DataTable();    

    // create SqlDataAdapter 
    using (var da = new SqlDataAdapter(query, cnn))
    {      
        // fill datatable
        da.Fill(dt);
    }

    return dt;
}

Затем вам нужно будет прочитать данные из таблицы данных. Смотрите мой ответ здесь , чтобы узнать, как читать данные Метод в связанном ответе использует расширение Field<T> из DataSetExtensions для извлечения данных. Пожалуйста, смотрите пример ниже:

// get data from your method
DataTable table = GetData("select * from MyTable");

// iterate over the rows of the datatable
foreach (var row in table.AsEnumerable())  // AsEnumerable() returns IEnumerable<DataRow>
{
    var id = row.Field<int>("ID");                           // int
    var name = row.Field<string>("Name");                    // string
    var orderValue = row.Field<decimal>("OrderValue");       // decimal
    var interestRate = row.Field<double>("InterestRate");    // double
    var isActive = row.Field<bool>("Active");                // bool
    var orderDate = row.Field<DateTime>("OrderDate");        // DateTime
}

Чтобы проверить, является ли DataTable нулевым / пустым, см. ответ . Это может быть так просто, как:

if(table?.Rows?.Count() > 0) { ... }
...