C # .Net 2.0에서 트랜잭션을 수행하는 가장 좋은 방법은 무엇입니까? 사용해야하는 수업은 무엇입니까? 커밋하고 롤백하는 모든 것들 등을 찾아야 할 함정은 무엇입니까? DB에 데이터를 삽입하는 동안 트랜잭션을 수행해야 할 프로젝트를 시작하고 있습니다. 거래에 대한 기본 사항에 대한 답변이나 링크는 환영합니다.
C # .Net 2.0에서 트랜잭션을 수행하는 가장 좋은 방법은 무엇입니까? 사용해야하는 수업은 무엇입니까? 커밋하고 롤백하는 모든 것들 등을 찾아야 할 함정은 무엇입니까? DB에 데이터를 삽입하는 동안 트랜잭션을 수행해야 할 프로젝트를 시작하고 있습니다. 거래에 대한 기본 사항에 대한 답변이나 링크는 환영합니다.
답변:
두 가지 주요 거래 유형이 있습니다. 연결 트랜잭션 및 주변 트랜잭션. 연결 트랜잭션 (예 : SqlTransaction)은 db 연결 (예 : SqlConnection)에 직접 연결됩니다. 즉, 연결을 계속 전달해야합니다. 경우에 따라 OK이지만 "만들기 / 사용 / 릴리스"는 허용하지 않습니다. 크로스 DB 작업을 허용하지 않습니다. 예 (공백 형식) :
using (IDbTransaction tran = conn.BeginTransaction()) {
try {
// your code
tran.Commit();
} catch {
tran.Rollback();
throw;
}
}
너무 지저분하지는 않지만 연결 "conn"으로 제한됩니다. 다른 메소드를 호출하려면 "conn"을 전달해야합니다.
대안은 주변 거래입니다. .NET 2.0의 새로운 기능인 TransactionScope 개체 (System.Transactions.dll)는 다양한 작업에서 사용할 수 있습니다 (적절한 공급자는 주변 트랜잭션에 자동으로 참여 함). 이를 통해 기존 (트랜잭션이 아닌) 코드를 쉽게 개조하고 여러 공급자와 대화 할 수 있습니다 (여러 개와 대화 할 경우 DTC가 관여 할 수 있음).
예를 들면 다음과 같습니다.
using(TransactionScope tran = new TransactionScope()) {
CallAMethodThatDoesSomeWork();
CallAMethodThatDoesSomeMoreWork();
tran.Complete();
}
여기서 두 가지 방법은 자체 연결 (개방 / 사용 / 닫기 / 처리)을 처리 할 수 있지만 아무 것도 전달하지 않아도 자동으로 주변 트랜잭션의 일부가됩니다.
코드 오류가 발생하면 Dispose ()가 Complete ()없이 호출되므로 롤백됩니다. 내부 트랜잭션을 롤백 할 수는 없지만 외부 트랜잭션을 완료 할 수는 있지만 예상되는 중첩 등이 지원됩니다. 누군가가 불행한 경우 트랜잭션이 중단됩니다.
TransactionScope의 다른 장점은 데이터베이스에만 국한되지 않는다는 것입니다. 모든 트랜잭션 인식 공급자가 사용할 수 있습니다. 예를 들어 WCF. 또는 트랜잭션 스코프 호환 객체 모델도 있습니다 (예 : 롤백 기능이있는 .NET 클래스-아마도이 방법을 사용한 적이 없지만 메멘토보다 쉽습니다).
대체로 매우 유용한 객체입니다.
몇 가지주의 사항 :
protected void Button1_Click(object sender, EventArgs e)
{
using (SqlConnection connection1 = new SqlConnection("Data Source=.\\SQLEXPRESS;AttachDbFilename=|DataDirectory|\\Database.mdf;Integrated Security=True;User Instance=True"))
{
connection1.Open();
// Start a local transaction.
SqlTransaction sqlTran = connection1.BeginTransaction();
// Enlist a command in the current transaction.
SqlCommand command = connection1.CreateCommand();
command.Transaction = sqlTran;
try
{
// Execute two separate commands.
command.CommandText =
"insert into [doctor](drname,drspecialization,drday) values ('a','b','c')";
command.ExecuteNonQuery();
command.CommandText =
"insert into [doctor](drname,drspecialization,drday) values ('x','y','z')";
command.ExecuteNonQuery();
// Commit the transaction.
sqlTran.Commit();
Label3.Text = "Both records were written to database.";
}
catch (Exception ex)
{
// Handle the exception if the transaction fails to commit.
Label4.Text = ex.Message;
try
{
// Attempt to roll back the transaction.
sqlTran.Rollback();
}
catch (Exception exRollback)
{
// Throws an InvalidOperationException if the connection
// is closed or the transaction has already been rolled
// back on the server.
Label5.Text = exRollback.Message;
}
}
}
}
DB 관련 항목에 필요한 경우 일부 OR 매퍼 (예 : NHibernate)는 기본적으로 트랜스 액 티노를 기본적으로 지원합니다.
또한 필요한 것에 따라 다릅니다. 기본 SQL 트랜잭션의 경우 코드에서 BEGIN TRANS 및 COMMIT TRANS를 사용하여 TSQL 트랜잭션을 시도 할 수 있습니다. 이것이 가장 쉬운 방법이지만 복잡성이 있으므로 올바르게 커밋하고 롤백해야합니다.
나는 같은 것을 사용할 것이다
SQLTransaction trans = null;
using(trans = new SqlTransaction)
{
...
Do SQL stuff here passing my trans into my various SQL executers
...
trans.Commit // May not be quite right
}
실패가 발생하면 using
트랜잭션이 커밋되거나 롤백됩니다 (할 일에 따라 다름). 우리가 직면 한 가장 큰 문제는 항상 최선을 다하는 것입니다. 를 사용하면 거래 범위가 제한됩니다.