2013-11-12 4 views
1

После открытия соединения, должен ли я явно закрыть его? или делает .net закрывать его автоматически? Как насчет того, если будет выбрано исключение?EF using и BeginTransaction, когда вызывать Connection.Close()?

using (DataContext pContext = new DataContext()) 
{ 
    pContext.Connection.Open() 

    using (var trx = pContext.Connection.BeginTransaction()) 
    { 
     //make changes to objects 

     //Make calls to ExecuteStoreCommand("Update table SET pee=1 AND poop=2 WHERE ETC"); 

     pContext.SaveChanges(); 

     trx.Commit(); 
    } 
} 

Выполняется ли pContext.Connection.Close() `во всех случаях посредством фреймворка? Я знаю, что в обычном использовании это делает, но как насчет того, когда я его вручную открываю?

Я использую Connection.BeginTransaction, потому что в моих тестах (используя только SaveChanges() без транзакций), если этот код выполняется и сбой по какой-либо причине, команды, отправленные во время ExecuteStoreCommand(), сохраняются, даже если изменения в моем объектов нет.

Я должен позвонить Connection.Open() перед вызовом pContext.Connection.BeginTransaction() в противном случае я получаю ошибку:

Inner Exception: 
The connection is not open. 

Любая помощь будет оценена.

+3

Вам не нужно вызывать 'pContext.Connection.Open()' –

+1

Что вы пытаетесь сделать и почему вы думаете, что вам нужно открыть соединение или сделка вообще? SaveChanges обычно заботится о соединениях и транзакциях –

+0

В этом заявлении я звоню в стандартные EF-обновления плюс ExecuteStoreCommand() и в своих тестах, не используя транзакцию, если происходит перехват, команды, отправленные в ExecuteStoreCommand(), сохраняются, а другие не. –

ответ

8

Не нужно вызывать DataContext.Connection.Open(). На самом деле, это плохая практика.

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

SaveChanges открывает соединение и транзакцию, поэтому нет необходимости вручную открывать соединение или запускать транзакцию. От the documentation:

SaveChanges operates within a transaction. SaveChanges will roll back that transaction and throw an exception if any of the dirty ObjectStateEntry objects cannot be persisted

Явное использование соединений и транзакций имеет смысл только если вы хотите, чтобы смешивать сырые команды SQL внутри сессии EF. Само по себе это не хорошая практика, но если это так, вам не нужно закрывать соединение, потому что DataContext закроет соединение, когда он будет удален. В документации имеется образец: How to: Manually Open the Connection from the Object Context

Вы также можете обрабатывать транзакцию с использованием TransactionScope, как описано в How to: Manage Transactions in the Entity Framework. В этом случае вам не нужно открывать соединение, так как все изменения автоматически зачисляются в текущую транзакцию. Это описано в http://msdn.microsoft.com/en-us/library/bb738523(v=vs.100).aspx и пример был бы:

using (DataContext pContext = new DataContext()) 
{ 

    using (TransactionScope transaction = new TransactionScope()) 
    { 
     //execute commands 



     pContext.SaveChanges(); 

     transaction.Complete() 
    } 
} 

В любом случае вручную обработки соединений и транзакций не является тривиальной.Вы должны прочитать Managing Connections and Transactions для некоторых вещей, которые вам нужно знать

+0

Без вызова: Connection.Open, я получаю ошибку Inner Exception: Соединение не открыто. –

+1

Да, потому что вы также пытаетесь запустить транзакцию ADO.NET. Дело в том, что вам обычно не нужно вручную играть с транзакциями и подключениями. –

+0

Таким образом, ответ не использует транзакции, просто используйте savechanges и решайте проблемы, если у вас возникло исключение. Я использовал native, потому что загрузка всех этих объектов в памяти просто для их удаления кажется ненужной. –

1

Это означает, что

using (DataContext pContext = new DataContext()) 

что pContext расположен после ухода using

это эквивалентно:

DataContext pContext = new DataContext() 
try 
{ 
    //do stuff here 
} 
finally 
{ 
    if(pContext!=null) 
     ((IDisposable)pContext).Dispose(); 
} 

так ответ -> Вам не нужно звонить близко после вашего код, поскольку

Connections are released back into the pool when you call Close or Dispose on the Connection..."

от here

+1

Я не вижу, как это отвечает на вопрос, ОП сказал, что знает, что делает блок использования. То, что он не знает, это если Dispose of EF закроет соединение, которое не было открыто EF. – nvoigt

+0

@nvoigt look for quoute – wudzik

Смежные вопросы