2015-10-28 4 views
1

Я схожу с ума от слежения, где возможно получить ошибку. Каждый раз, когда я нажимаю кнопку «Получить». Это дает мне ошибку исключения, которая говоритСостояние связи не было закрыто

Соединение не было закрыто. Текущее состояние подключения - .

Вот код позади

void GetReceiptNo(int ID) 
{ 
    con.Open(); 
    SqlCommand cmd = new SqlCommand(); 
    //cmd.Connection = con; 
    cmd.Connection.Open(); 
    cmd.CommandText = "SELECT ReceiptNo FROM PurchaseOrder WHERE [email protected]"; 
    cmd.Parameters.AddWithValue("@PONo", ID); 
    SqlDataReader dr = cmd.ExecuteReader(); 
    if (dr.HasRows) 
    { 
     while (dr.Read()) 
     { 
      txtReceiptNo.Text = dr["ReceiptNo"].ToString(); 

     } 
    } 
    else 
    { 
     con.Close(); 
     Response.Redirect("~/PurchaseOrder/MaterialsReceive.aspx"); 
    } 
    if (cmd.Connection.State == ConnectionState.Open) 
    { 
     cmd.Connection.Close(); 
    } 
} 

void UpdateInventory(string itemID, string quantity) 
{ 

    con.Open(); 
    SqlCommand cmd = new SqlCommand(); 
    cmd.Connection = con; 
    cmd.CommandText = "INSERT INTO Receiving VALUES (@ItemNo, @Quantity, @Timestamp); " + 
     "UPDATE RMInventory SET Available = Available + @Quantity WHERE [email protected]; " + 
     "UPDATE PODetails SET Status = 'Received' WHERE [email protected] AND Status='Process' " + 
     "UPDATE PurchaseOrder SET Status = 'Received' WHERE [email protected] AND Status='Processing' " + 
     "UPDATE PurchaseOrder SET [email protected] WHERE [email protected]"; 
    cmd.Parameters.AddWithValue("@PONo", Request.QueryString["ID"].ToString()); 
    cmd.Parameters.AddWithValue("@ItemNo", itemID); 
    cmd.Parameters.AddWithValue("@Quantity", quantity); 
    cmd.Parameters.AddWithValue("@Timestamp", DateTime.Now); 
    cmd.Parameters.AddWithValue("@DateReceived", DateTime.Now); 
    cmd.ExecuteNonQuery(); 
    con.Close(); 
} 

Ошибка появится на пустом UpdateInventory
con.Open()

+0

- это ваше приложение, используя потоки в любом случае? Если это так, вам лучше было бы позволить каждому вызову построить собственное соединение или использовать блокировку или мьютекс, чтобы гарантировать, что два вызова не пытаются открыть/закрыть одно и то же соединение. –

+0

cmd.Connection = con, почему эта строка прокомментирована, в настоящее время Я не вижу никакой связи между объектом Command и объектом Connection –

ответ

2

Try использовать using заявление, когда вы имеете дело с соединениями. Это поможет вам справиться с этими ситуациями.

using(var con = new SqlConnection(connectionString)) 
using(var cmd = new SqlCommand(query, con)) 
{ 
    con.Open(); 
    //your code 
} 

И если вы не используете using заявление (, который идеально рекомендованную), то вы можете поместить свой код внутри попытке поймать и, наконец, блокировать и попытаться закрыть соединение внутри окончательно блокировать, как это:

try 
{ 
    con.Open(); 
    SqlCommand cmd = new SqlCommand(query, con); 

    cmd.ExecuteNonQuery();  
    con.Close();  
}  
catch (Exception ex) 
{ 
} 
finally 
{ 
    con.close(); 
} 
1

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

using statement - лучший способ сделать это.

using(var con = new SqlConnection(conString)) 
using(var cmd = con.CreateCommand()) 
{ 
    // Define your CommandText 
    // Add your parameters 
    // Execute your query 
} 

Вы также можете использовать его с вашим считывающим устройством. Также не используйте метод AddWithValue. It may generate unexpected and surprising results sometimes. Используйте Add method перегрузки, чтобы указать свой тип параметра и его размер.

0

ИМХО выпускать здесь разные, следующие два метода твоего:

void GetReceiptNo(int ID) 
void UpdateInventory(string itemID, string quantity) 

Как получить доступ к Connection объект, который не является локальным для них, как они делают работу открытия Connection и закрытие он завершает выполнение в конце, но здесь кажется, так как соединение является общим, поэтому, когда оно уже открыто в одном, другое пытается открыть его, и вы получите эту проблему. Его вроде GetReceiptNo уже открыл соединение, и перед его закрытием вызывается UpdateInventory, и он выдает ошибку при попытке открыть уже открытое соединение. В большинстве случаев это может происходить, когда эти вызовы работают параллельно, когда они разделяют контекст connection между ними.Теперь, пожалуйста, помните, важный аспект:

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

Лучший вариант для вас было бы сделать каждый из метода имеют локальный объект связи, как это было предложено ранее иметь using заявление для обоих соединений и командных объектов, таких как:

using(SqlConnection conn = new SQlConnection(connectionString) 
{ 
    using (SQlCommand cmd = new SQlCommand(conn) 
    { 
    // Remaining logic 
    } 
} 

Это избавит вас от вопроса обо всех методах, подобных двум упомянутым выше вызовам одновременно. Однако в случае, если изменение не представляется возможным, то ввести следующий код:

if (conn.State != ConnectionState.Open) 
    conn.Open() 

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