2012-03-23 1 views
1
using System; 
using System.Collections.Generic; 
using System.Linq; 
using System.Text; 
using System.Data.SqlClient; 
using System.ComponentModel.DataAnnotations; 
using System.Data.Entity; 

namespace SqlEFTester { 
    class Program { 
     static void Main(string[] args) { 

      ConnectionManager connectionManager = new ConnectionManager(); 
      SqlConnection conn = connectionManager.Connection; 
      conn.Open(); 

      //BEGIN TRAN 
      SqlTransaction tran = conn.BeginTransaction(); 

      //Will do some legacy work using SqlTransaction, so can not use TransactionScope here. 

      MyContext context = new MyContext(conn); 
      List<Inventory> list = context.Inventories.Take(10).ToList();//Just get top 10 Inventories 

      //COMIT TRAN 
      tran.Commit(); 

      Console.WriteLine("Done..."); 
      Console.ReadLine(); 
     } 
    } 

class ConnectionManager { 
    public SqlConnection Connection { 
     get { 
      return new SqlConnection("Data Source=MYSERVER;Initial Catalog=MYDATABASE;Integrated Security=SSPI;"); 
     } 
    } 
} 

[Table("Inventory")] 
class Inventory { 
    [Key] 
    public int InventoryId { get; set; } 
} 

class MyContext : DbContext { 
    public EmutContext(SqlConnection conn) 
     : base(conn, false) { 
     //I have to close it, otherwise it will say "EntityConnection can only be constructed with a closed DbConnection." 
      base.Database.Connection.Close(); 
    } 

    public DbSet<Inventory> Inventories { get; set; } 
} 

전통적인 ADO.NET SqlTransaction 내부에서 EF 코드를 실행하려고합니다.이 SqlTransaction이 완료되었습니다. 더 이상 사용할 수 없습니다. 엔티티 프레임 워크 코드 우선

연결을 열고 EF에 동일한 연결을 전달하여 연결을 다시 사용합니다. 의도적으로 연결을 닫아야합니다.

EntityConnection은 닫힌 DbConnection으로 만 구성 할 수 있습니다. 나는 위의 코드를 실행하면

나는

트랜잭션이 완료되었다.

커밋 할 수 없습니다. 참고 : 우리가 사용하는 레거시 코드 프레임 워크 때문에 TransactionScope을 사용할 수 없습니다.

+0

당신이 conn.Open라고하기 전에 EmutContext을 만들려고 마십시오 (이도록 SqlConnection을 열 것이다) 나는 상황에 폐쇄도록 SqlConnection을 전달하고 있습니다? 코드에서 연결을 닫으면 트랜잭션이 완료되고 커밋 전에 트랜잭션이 닫힙니다. – Artem

+0

conn.Open() 바로 전에 컨텍스트 생성을 이동하면 "EntityConnection은 닫힌 DbConnection으로 만 생성 할 수 있습니다."라는 메시지가 나타납니다. 코드 줄을이 ConnectionManager connectionManager = new ConnectionManager(); SqlConnection conn = connectionManager.Connection; MyContext context = 새로운 MyContext (conn); conn.Open(); – sadhat75

답변

2

글쎄, 나는 TransactionScope를 사용하는 것이 좋지만, 대안으로 리플렉션을 시도해 볼 수있다. 를 연 다음의 EntityConnection이

 //create connection & context 
     SqlConnection sqlConnection = new SqlConnection("your connection"); 
     YourDbContext context = new YourDbContext(sqlConnection, false); 

     var entityConnection = (EntityConnection)((IObjectContextAdapter)context).ObjectContext.Connection; 
     try 
     { 
      //open entity connection - will open store connection 
      entityConnection.Open(); 

      var entityTransaction = entityConnection.BeginTransaction(); 

      //get sql transaction via reflection 
      var sqlTransaction = (SqlTransaction)entityTransaction.GetType() 
                 .InvokeMember("StoreTransaction", 
                    BindingFlags.FlattenHierarchy | BindingFlags.NonPublic | BindingFlags.InvokeMethod 
                    | BindingFlags.Instance | BindingFlags.GetProperty | BindingFlags.NonPublic, null, entityTransaction, new object[0]); 



      //here you got both sql transaction & sql connectont 
      var cmd = sqlConnection.CreateCommand(); 
      cmd.Transaction = sqlTransaction; 
      cmd.CommandText = "your sql statement"; 
      cmd.ExecuteNonQuery(); 

      //do your context work - will be in entity transaction 

      //invoke save changes 
      context.SaveChanges(); 

      entityTransaction.Commit(); 
     } 
     finally 
     { 
      entityConnection.Close(); 
     } 
+0

리플렉션을 사용하는 대신이 작업이 필요합니까? ((IDbCommand) cmd) .Transaction = conn.BeginTransaction(); ? – Pawel

+0

@Pawel이 방법으로 SqlTransaction을 만들면 안타깝게도 EntityConnection을 사용하여 실행하는 모든 쿼리 (예 : 작성자가 언급 한 linq 쿼리를 비롯한 모든 컨텍스트 쿼리)는이 트랜잭션을 사용하지 않습니다. 동일한 트랜잭션 내에서 컨텍스트 쿼리와 원시 sql을 모두 실행해야하는 경우 TransactionScope를 사용해야합니다. 저자는 TransactionScope을 사용할 수 없다고 언급 했으므로이 작은 샘플을 작성하여 EntityTransaction에서 SqlTransaction을 검색하는 방법을 작성했습니다.이 트랜잭션은 컨텍스트 쿼리와 원시 SQL을 동일한 트랜잭션 내에서 실행할 수 있습니다. 나는 반사 때문에이 방법을 좋아하지 않는다. – Artem

관련 문제