2016-12-03 2 views
1

Я использую Asp.Net MVC и Entity Framework. У меня есть класс для управления сделкой по запросу следующим образом:Транзакция по запросу в нескольких dbcontext в EntityFramework

public class TransactionPerRequest : 
    IRunOnEachRequest, IRunOnError, IRunAfterEachRequest 
{ 
    private readonly ContextDB _Context; 
    private readonly HttpContextBase _HttpContext; 

    public TransactionPerRequest(ContextDB context, 
     HttpContextBase httpContext) 
    { 
     _Context = context; 
     _HttpContext = httpContext; 
    } 

    void IRunOnEachRequest.Execute() 
    { 
     _HttpContext.Items["_Transaction"] = 
      _Context.Database.BeginTransaction(IsolationLevel.ReadCommitted); 
    } 

    void IRunOnError.Execute() 
    { 
     _HttpContext.Items["_Error"] = true; 
    } 

    void IRunAfterEachRequest.Execute() 
    { 
     var transaction = (DbContextTransaction)_HttpContext.Items["_Transaction"]; 

     if (_HttpContext.Items["_Error"] != null) 
      transaction.Rollback(); 
     else 
      transaction.Commit(); 
    } 
} 

Я хочу использовать несколько контексты, как описано here

Как я могу изменить TransactionPerRequset класс?

ответ

1

Я сделал это,

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

Чтобы сделать это, вы будете использовать следующие базы DbContext конструктор: DbContext(DbConnection connection, Boolean contextOwnsConnection)

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

Вы должны подвергать конструктор с DbConnection во всех ваших прикладных контекстах и ​​впрыснуть же соединение вы создали вне DbContext. Таким образом, EF не создаст и не откроет их.

Наконец, в вашем диспетчере соединений вы можете использовать DbConnection.BeginTransaction(), чтобы получить объект DbTransaction и работать с ним в соответствии с вашими потребностями.

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

public partial class ContextDB : DbContext 
{ 
    // New constructor 
    public ContextDB(DbConnection connection) 
     : base(connection, false) 
    { 
    } 
} 

public class TransactionPerRequest : 
    IRunOnEachRequest, IRunOnError, IRunAfterEachRequest 
{ 
    private readonly ContextDB _Context; 
    private readonly HttpContextBase _HttpContext; 
    private readonly DbConnection _cnn; 

    public TransactionPerRequest(HttpContextBase httpContext) 
    { 
     // Your code creates the connection 
     _cnn = new SqlConnection("Data Source=.;Initial Catalog=DB;Integrated Security=SSPI;"); 
     // Pass connection your context 
     _Context = new ContextDB(_cnn); 
     _HttpContext = httpContext; 
    } 

    void IRunOnEachRequest.Execute() 
    { 
     // Open connection 
     _cnn.Open(); 
     _HttpContext.Items["_Transaction"] = 
      _cnn.BeginTransaction(IsolationLevel.ReadCommitted); 
    } 

    void IRunOnError.Execute() 
    { 
     _HttpContext.Items["_Error"] = true; 
    } 

    void IRunAfterEachRequest.Execute() 
    { 
     var transaction = (DbContextTransaction)_HttpContext.Items["_Transaction"]; 

     if (_HttpContext.Items["_Error"] != null) 
      transaction.Rollback(); 
     else 
      transaction.Commit(); 

     _cnn.Close(); 
     _cnn.Dispose(); 
    } 
} 
+0

Можете ли вы объяснить о инициализации, открытии, закрытии и удалении соединения? Благодарю. –

+0

Я имел в виду основы работы с подключением к базе данных, вы не хотите, чтобы они оставались открытыми или не располагались. –