Есть ли способ иметь SqlConnection, который будет писать, когда связанный DataReader открыт? - PullRequest
2 голосов
/ 18 декабря 2009

Или каков рекомендуемый способ чтения и записи одновременно? Наличие двух открытых соединений - единственный способ? Это обычное приложение Windows Forms C # (.NET 3.5)

using (SqlConnection conn = new SqlConnection(connStr)) {
    SqlCommand cmdRead = new SqlCommand("select stools from foo", conn);
    SqlDataReader rdr = cmdRead.ExecuteReader();
    SqlCommand cmdWrite = new SqlCommand("insert into bar values (@beer)", conn);
    SqlParameter beer = new SqlParameter("@beer", SqlDbType.Int);
    cmdWrite.Parameters.Add(beer);
    while(rdr.Read()) {
        int stools = rdr.GetInt32(0);
        cmdWrite.Parameters["@beer"].value = stools;
        //Next line fails for an open data reader associated to the "command"
        cmdWrite.ExecuteNonQuery(); 
    }
    rdr.Close()
}

Это, OTOH, работает, но мне некрасиво (кроме открытия дополнительного соединения)

using (SqlConnection connR = new SqlConnection(connStr)) {
    using (SqlConnection connW = new SqlConnection(connStr)) {
        SqlCommand cmdRead = new SqlCommand("select stools from foo", connR);
        SqlDataReader rdr = cmdRead.ExecuteReader();
        SqlCommand cmdWrite = new 
                         SqlCommand("insert into bar values (@beer)", connW);
        SqlParameter beer = new SqlParameter("@beer", SqlDbType.Int);
        cmdWrite.Parameters.Add(beer);
        while(rdr.Read()) {
            int stools = rdr.GetInt32(0);
            cmdWrite.Parameters["@beer"].value = stools;
            cmdWrite.ExecuteNonQuery(); 
        }
        rdr.Close()
    }
}

В этом простом случае прочитайте все табуреты, сохраните их в списке, закройте читатель, а затем запишите, что они будут работать (если в базе данных не так много табуретов), но в более сложных случаях он начинается быть громоздким и требовательным к памяти, так что это тоже не желательно.

Ответы [ 4 ]

3 голосов
/ 18 декабря 2009

В SQL 2005 и более поздних версиях вы можете использовать несколько активных наборов результатов (MARS):

http://msdn.microsoft.com/en-us/library/ms345109%28SQL.90%29.aspx

http://msdn.microsoft.com/en-us/library/ms131686.aspx

Чтобы это работало, вам нужно включить его в строке подключения.

2 голосов
/ 18 декабря 2009

Почему бы не использовать два метода: один для чтения и один для записи, каждый из которых использует свое собственное соединение, полученное из пула соединений.

Чтение

using (SqlConnection conn = new SqlConnection(connStr))
using (SqlCommand cmdRead = new SqlCommand("select stools from foo", conn))
{
    conn.Open();  
    using (SqlDataReader rdr = cmdRead.ExecuteReader())
    {
        while(rdr.Read()) 
        {
            int stools = rdr.GetInt32(0);
        }
    }
}

Пишущий

using (SqlConnection conn = new SqlConnection(connStr))
using (SqlCommand cmdWrite = new SqlCommand("insert into bar values (@beer)", conn))
{
    conn.Open();
    SqlParameter beer = new SqlParameter("@beer", SqlDbType.Int);
    cmdWrite.Parameters.Add(beer);
    cmdWrite.Parameters["@beer"].value = stools;
    cmdWrite.ExecuteNonQuery(); 
}

А потом просто вызывайте их в разных темах. Это делает методы более четкими и конкретными.

1 голос
/ 18 декабря 2009

Ну, очевидный вопрос, почему вы вообще делаете это в коде?

Вы выбираете из одной таблицы запись в другую - это крики вставляют мне запрос.

Несомненно, пример из реального мира более сложен, и в этом случае вам нужно два соединения, потому что устройства чтения данных работают, удерживая соединение открытым до тех пор, пока вы закончите, и это более или менее так.

1 голос
/ 18 декабря 2009

Вы не можете писать, когда DataReader открыт, в этой ситуации необходимо создать второе соединение, и, IMHO, это не проблема проектирования.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...