Not
Bu sayfaya erişim yetkilendirme gerektiriyor. Oturum açmayı veya dizinleri değiştirmeyi deneyebilirsiniz.
Bu sayfaya erişim yetkilendirme gerektiriyor. Dizinleri değiştirmeyi deneyebilirsiniz.
sınıfı, TransactionScope işlemle etkileşim kurmanıza gerek kalmadan bir kod bloğunu bir işleme katılan olarak işaretlemek için basit bir yol sağlar. İşlem kapsamı ortam işlemini otomatik olarak seçebilir ve yönetebilir. Kullanım kolaylığı ve verimliliği nedeniyle, bir işlem uygulaması geliştirirken sınıfını TransactionScope kullanmanız önerilir.
Ayrıca, kaynakları işlemle açıkça listelemeniz gerekmez. Bir System.Transactions kaynak yöneticisi (örneğin, SQL Server 2005), kapsam tarafından oluşturulan bir ortam işleminin varlığını algılayabilir ve otomatik olarak listeye alabilir.
İşlem kapsamı oluşturma
Aşağıdaki örnekte sınıfının basit kullanımı gösterilmektedir TransactionScope .
// This function takes arguments for 2 connection strings and commands to create a transaction
// involving two SQL Servers. It returns a value > 0 if the transaction is committed, 0 if the
// transaction is rolled back. To test this code, you can connect to two different databases
// on the same server by altering the connection string, or to another 3rd party RDBMS by
// altering the code in the connection2 code block.
static public int CreateTransactionScope(
string connectString1, string connectString2,
string commandText1, string commandText2)
{
// Initialize the return value to zero and create a StringWriter to display results.
int returnValue = 0;
System.IO.StringWriter writer = new System.IO.StringWriter();
try
{
// Create the TransactionScope to execute the commands, guaranteeing
// that both commands can commit or roll back as a single unit of work.
using (TransactionScope scope = new TransactionScope())
{
using (SqlConnection connection1 = new SqlConnection(connectString1))
{
// Opening the connection automatically enlists it in the
// TransactionScope as a lightweight transaction.
connection1.Open();
// Create the SqlCommand object and execute the first command.
SqlCommand command1 = new SqlCommand(commandText1, connection1);
returnValue = command1.ExecuteNonQuery();
writer.WriteLine("Rows to be affected by command1: {0}", returnValue);
// If you get here, this means that command1 succeeded. By nesting
// the using block for connection2 inside that of connection1, you
// conserve server and network resources as connection2 is opened
// only when there is a chance that the transaction can commit.
using (SqlConnection connection2 = new SqlConnection(connectString2))
{
// The transaction is escalated to a full distributed
// transaction when connection2 is opened.
connection2.Open();
// Execute the second command in the second database.
returnValue = 0;
SqlCommand command2 = new SqlCommand(commandText2, connection2);
returnValue = command2.ExecuteNonQuery();
writer.WriteLine("Rows to be affected by command2: {0}", returnValue);
}
}
// The Complete method commits the transaction. If an exception has been thrown,
// Complete is not called and the transaction is rolled back.
scope.Complete();
}
}
catch (TransactionAbortedException ex)
{
writer.WriteLine("TransactionAbortedException Message: {0}", ex.Message);
}
// Display messages.
Console.WriteLine(writer.ToString());
return returnValue;
}
' This function takes arguments for 2 connection strings and commands to create a transaction
' involving two SQL Servers. It returns a value > 0 if the transaction is committed, 0 if the
' transaction is rolled back. To test this code, you can connect to two different databases
' on the same server by altering the connection string, or to another 3rd party RDBMS
' by altering the code in the connection2 code block.
Public Function CreateTransactionScope( _
ByVal connectString1 As String, ByVal connectString2 As String, _
ByVal commandText1 As String, ByVal commandText2 As String) As Integer
' Initialize the return value to zero and create a StringWriter to display results.
Dim returnValue As Integer = 0
Dim writer As System.IO.StringWriter = New System.IO.StringWriter
Try
' Create the TransactionScope to execute the commands, guaranteeing
' that both commands can commit or roll back as a single unit of work.
Using scope As New TransactionScope()
Using connection1 As New SqlConnection(connectString1)
' Opening the connection automatically enlists it in the
' TransactionScope as a lightweight transaction.
connection1.Open()
' Create the SqlCommand object and execute the first command.
Dim command1 As SqlCommand = New SqlCommand(commandText1, connection1)
returnValue = command1.ExecuteNonQuery()
writer.WriteLine("Rows to be affected by command1: {0}", returnValue)
' If you get here, this means that command1 succeeded. By nesting
' the using block for connection2 inside that of connection1, you
' conserve server and network resources as connection2 is opened
' only when there is a chance that the transaction can commit.
Using connection2 As New SqlConnection(connectString2)
' The transaction is escalated to a full distributed
' transaction when connection2 is opened.
connection2.Open()
' Execute the second command in the second database.
returnValue = 0
Dim command2 As SqlCommand = New SqlCommand(commandText2, connection2)
returnValue = command2.ExecuteNonQuery()
writer.WriteLine("Rows to be affected by command2: {0}", returnValue)
End Using
End Using
' The Complete method commits the transaction. If an exception has been thrown,
' Complete is called and the transaction is rolled back.
scope.Complete()
End Using
Catch ex As TransactionAbortedException
writer.WriteLine("TransactionAbortedException Message: {0}", ex.Message)
End Try
' Display messages.
Console.WriteLine(writer.ToString())
Return returnValue
End Function
İşlem kapsamı, yeni TransactionScope bir nesne oluşturduğunuzda başlatılır. Kod örneğinde gösterildiği gibi, kapsamları bir using deyimiyle oluşturmanız önerilir.
using deyimi hem C# hem de Visual Basic'te kullanılabilir ve try...finally bloğu gibi çalışarak kapsamın düzgün bir şekilde bertaraf edildiğinden emin olur.
örneği TransactionScopeoluşturduğunuzda, hangi işleme katılılacağı işlem yöneticisi tarafından belirlenir. Kapsam belirlendikten sonra her zaman bu işlemin bir parçası olur. Karar iki faktöre dayanır: ortam işleminin mevcut olup olmadığı ve oluşturucudaki parametrenin TransactionScopeOption değeri. Ortam işlemi, kodunuzun yürütüldiği işlemdir. Sınıfın statik Transaction.Current özelliğini Transaction çağırarak ortam işlemine başvuru alabilirsiniz. Bu parametrenin nasıl kullanıldığı hakkında daha fazla bilgi için bu konunun TransactionScopeOption kullanarak işlem akışını yönetme bölümüne bakın.
İşlem kapsamını tamamlama
Uygulamanız bir işlemde gerçekleştirmek istediği tüm işi tamamladığında, işlem yöneticisine işlemin işlenmesinin TransactionScope.Complete kabul edilebilir olduğunu bildirmek için yöntemini yalnızca bir kez çağırmanız gerekir.
Complete çağrısını using bloğundaki son deyim olarak kullanmak çok iyi bir uygulamadır.
İşlem yöneticisi bunu bir sistem hatası olarak veya işlem kapsamında oluşan bir özel duruma eşdeğer olarak yorumladığı için bu yöntemin çağrılamaması işlemi durdurur. Ancak, bu yöntemin çağrılması işlemin gerçekleştirildiğini garanti etmez. Bu yalnızca durumunuzu işlem yöneticisine bildirmenin bir yoludur. yöntemi çağırdıktan Complete sonra, Current özelliğini kullanarak çevresel işleme artık erişemezsiniz ve bunu yapmaya çalışırsanız bir hata fırlatılır.
TransactionScope Nesne başlangıçta işlemi oluşturduysa, işlem yöneticisi tarafından işlemin gerçek olarak işlenmesi, bloktaki son kod satırından using sonra gerçekleşir. İşlemi oluşturmadıysa, nesnenin sahibi Commit tarafından her CommittableTransaction çağrıldığında işleme gerçekleşir. Bu noktada işlem yöneticisi kaynak yöneticilerini çağırır ve nesne üzerinde Complete yöntemi çağrılıp çağrılmadığına bağlı olarak onları ya işleme ya da geri alma konusunda bilgilendirir.
Bu using deyimi, bir özel durum oluştuğunda bile Dispose nesnesinin TransactionScope yönteminin çağrılmasını sağlar. yöntemi, Dispose işlem kapsamının sonunu işaretler. Bu yöntem çağrıldıktan sonra oluşan özel durumlar işlemi etkilemeyebilir. Bu yöntem ayrıca ortam işlemini önceki durumuna geri yükler.
İşlem kapsam tarafından oluşturulursa ve işlem durdurulursa bir TransactionAbortedException fırlatılır. Bir TransactionInDoubtException fırlatılırsa, işlem yöneticisi bir İşleme kararına ulaşamaz. İşlem onaylanırsa herhangi bir istisna atılmaz.
bir işlemi geri döndürme
İşlemi geri döndürmek istiyorsanız, işlem kapsamında Complete yöntemini çağırmamalısınız. Örneğin, kapsam içinde bir özel durum oluşturabilirsiniz. Katıldığı işlem geri alınmış olacak.
TransactionScopeOption kullanarak işlem akışını yönetme
İşlem kapsamı, aşağıdaki örnekte TransactionScope yönteminde olduğu gibi, kendi kapsamını kullanan bir yöntemi içeren başka bir yöntem çağrılarak iç içe yerleştirilebilir.
void RootMethod()
{
using(TransactionScope scope = new TransactionScope())
{
/* Perform transactional work here */
SomeMethod();
scope.Complete();
}
}
void SomeMethod()
{
using(TransactionScope scope = new TransactionScope())
{
/* Perform transactional work here */
scope.Complete();
}
}
En üstteki işlem kapsamı kök kapsam olarak adlandırılır.
Sınıf, TransactionScope kapsamın işlem davranışını tanımlayan türdeki TransactionScopeOption bir numaralandırmayı kabul eden birkaç aşırı yüklenmiş oluşturucu sağlar.
Bir TransactionScope nesnenin üç seçeneği vardır:
Ortam işlemine katılın veya mevcut değilse yeni bir işlem oluşturun.
Yeni bir kök kapsam oluşturun, yani yeni bir işlem başlatın ve bu işlemin kendi kapsamındaki yeni ortam işlemi olmasını sağlayın.
Bir işleme hiç katılmayın. Sonuç olarak ortam işlemi yoktur.
Kapsam Required ile örneklendirilirse ve bir ortam işlemi mevcutsa, kapsam bu işleme katılır. Eğer, diğer taraftan, bir çevresel işlem yoksa, kapsam yeni bir işlem oluşturur ve kök kapsam haline gelir. Bu varsayılan değerdir. Required kullanıldığında, kapsam içindeki kodun kök olması ya da mevcut ortam işlemine katılması gerekip gerekmediği konusunda farklı davranmasına gerek yoktur. Her iki durumda da aynı şekilde çalışması gerekir.
Kapsam ile RequiresNewörneği oluşturulursa, her zaman kök kapsamdır. Yeni bir işlem başlatır ve onun işlemi kapsamın içindeki yeni ortam işlemi olur.
Kapsam Suppress ile örneklendirildiğinde, bir ortam işlemi mevcut olup olmadığına bakılmaksızın hiçbir zaman bir işleme katılmaz. Bu değerle başlatılan bir kapsamın her zaman null ortam işlemi vardır.
Yukarıdaki seçenekler aşağıdaki tabloda özetlenmiştir.
| İşlemKapsamSeçeneği | Ortam İşlemi | Kapsam, yer alır |
|---|---|---|
| Gerekli | Hayı | Yeni İşlem (kök olacaktır) |
| Yeni Gerektirir | Hayı | Yeni İşlem (kök olacaktır) |
| Bastırmak | Hayı | İşlem Yok |
| Gerekli | Evet | Ortam İşlemi |
| Yeni Gerektirir | Evet | Yeni İşlem (kök olacaktır) |
| Bastırmak | Evet | İşlem Yok |
Bir TransactionScope nesne mevcut bir ortam işlemine katıldığında kapsam nesnesinin atılması, kapsam işlemi durdurmadığı sürece işlemi sonlandıramayabilir. Kök kapsam tarafından oluşturulan bir ortam işlemi varsa, yalnızca kök kapsam temizlendiğinde, işlemde Commit çağrılır. İşlem el ile oluşturulduysa, işlem durdurulduğunda veya oluşturucusu tarafından işlendiğinde sona erer.
Aşağıdaki örnek, her biri farklı bir TransactionScope değerle örneklenen üç iç içe kapsam nesnesi oluşturan bir TransactionScopeOption nesnesini göstermektedir.
using(TransactionScope scope1 = new TransactionScope())
//Default is Required
{
using(TransactionScope scope2 = new TransactionScope(TransactionScopeOption.Required))
{
//...
}
using(TransactionScope scope3 = new TransactionScope(TransactionScopeOption.RequiresNew))
{
//...
}
using(TransactionScope scope4 = new TransactionScope(TransactionScopeOption.Suppress))
{
//...
}
}
Örnekte, herhangi bir ortam işlemi olmadan yeni bir kapsam (scope1) oluşturan bir kod bloğu (Required ile) gösterilmektedir. Kapsam scope1 , yeni bir işlem (İşlem A) oluşturduğundan ve İşlem A'nın ortam işlemi olmasını sağladığından bir kök kapsamdır.
Scope1 ardından her birinin farklı TransactionScopeOption bir değere sahip olduğu üç nesne daha oluşturur. Örneğin, scope2Required ile oluşturulur ve bir ortam işlemi olduğundan, scope1 tarafından oluşturulan ilk işlemi birleştirir.
scope3 Yeni bir işlemin kök kapsamı olduğunu ve scope4 ortam işlemi olmadığını unutmayın.
varsayılan ve en yaygın kullanılan değeri TransactionScopeOption olsa Requiredda, diğer değerlerin her birinin benzersiz bir amacı vardır.
İşlem kapsamı içinde işlem dışı kod
Suppress kod bölümü tarafından gerçekleştirilen işlemleri korumak istediğinizde ve işlemler başarısız olursa ortam işlemini durdurmak istemediğinizde yararlıdır. Örneğin, günlük veya denetim işlemleri gerçekleştirmek istediğinizde veya ortam işleminizin taahhüt veya iptal edilmesinden bağımsız olarak olayları abonelere yayımlamak istediğinizde. Bu değer, aşağıdaki örnekte gösterildiği gibi işlem kapsamı içinde işlem dışı bir kod bölümüne sahip olmanıza olanak tanır.
using(TransactionScope scope1 = new TransactionScope())
{
try
{
//Start of non-transactional section
using(TransactionScope scope2 = new
TransactionScope(TransactionScopeOption.Suppress))
{
//Do non-transactional work here
}
//Restores ambient transaction here
}
catch {}
//Rest of scope1
}
İç içe yerleştirilmiş kapsam içinde oylama
İç içe yerleştirilmiş bir kapsam, kök kapsamın ortam işlemini birleştirebilse de, iç içe kapsamda Complete çağrıldığında kök kapsam üzerinde hiçbir etkisi olmaz. İşlem yalnızca kök kapsamdan iç içe geçen son kapsama kadar tüm kapsamlar işlemi işlemeye oy verirse işlenir. ortam işlemi hemen durdurulacağı için iç içe bir kapsamda çağrı Complete yapılmaması kök kapsamı etkiler.
TransactionScope zaman aşımını ayarlama
Bazı TransactionScope aşırı yüklenmiş oluşturucuları, işlemin zaman aşımını denetlemek için kullanılan TimeSpan türündeki bir değeri kabul eder. Sıfır olarak ayarlanan zaman aşımı, sonsuz bir zaman aşımı anlamına gelir. Kodunuzda adım adım ilerleyerek iş mantığınızdaki bir sorunu izole etmek istediğinizde ve sorunu bulmaya çalışırken hata ayıklamakta olduğunuz işlemin zaman aşımına uğramasını istemediğinizde, sonsuz zaman aşımı çoğunlukla hata ayıklama için yararlıdır. İşlem kilitlenmelerine karşı korumaları geçersiz kılacağından, diğer tüm durumlarda sonsuz zaman aşımı değerini kullanırken son derece dikkatli olun.
Genellikle iki durumda zaman aşımını TransactionScope varsayılan değerlerden farklı değerlere ayarlarsınız. İlki, uygulamanızın durdurulan işlemleri işleme biçimini test etmek istediğiniz geliştirme sırasındadır. Zaman aşımını küçük bir değere (bir milisaniye gibi) ayarlayarak işleminizin başarısız olmasına neden olursunuz ve bu nedenle hata işleme kodunuzu gözlemleyebilirsiniz. Değeri varsayılan zaman aşımından küçük olarak ayarladığınız ikinci durum, kapsamın kaynak çekişmesi içinde yer aldığını ve kilitlenmelere neden olduğunu düşünmenizdir. Bu durumda, işlemi en kısa sürede durdurmak ve varsayılan zaman aşımının süresinin dolmasını beklememek istersiniz.
Kapsam bir ortam işlemini birleştirdiğinde ancak ortam işleminin ayarlandığı işlemden daha küçük bir zaman aşımı belirttiğinde, TransactionScope nesneye yeni, daha kısa zaman aşımı uygulanır ve kapsam belirtilen süre içinde bitmelidir, aksi halde işlem otomatik olarak sonlandırılır. İç içe kapsamın zaman aşımı, ortam işleminin zaman aşımından daha fazlaysa, hiçbir etkisi olmaz.
TransactionScope yalıtım düzeyini ayarlama
TransactionScope'nin aşırı yüklenmiş oluşturucularından bazıları, bir zaman aşımı değerine ek olarak yalıtım düzeyini belirtmek için TransactionOptions türünde bir yapı kabul eder. Varsayılan olarak, işlem yalıtım düzeyi olarak ayarlanmış şekilde Serializableyürütülür. Serializable haricinde bir yalıtım düzeyi seçmek, okuma yoğun sistemler için yaygın olarak kullanılır. Bunun için işlem işleme teorisinin ve işlemin semantiğinin, ilgili eşzamanlılık sorunlarının ve sistem tutarlılığının sonuçlarının sağlam bir şekilde anlaşılması gerekir.
Buna ek olarak, tüm kaynak yöneticileri tüm yalıtım düzeylerini desteklemez ve yapılandırılandan daha yüksek bir düzeyde işlemde yer almayı seçebilir.
Serializable dışındaki her yalıtım düzeyi, aynı bilgilere erişen diğer işlemlerden kaynaklanan tutarsızlığa açıktır. Farklı yalıtım düzeyleri arasındaki fark, okuma ve yazma kilitlerinin kullanılmasıdır. Kilit yalnızca işlem kaynak yöneticisindeki verilere eriştiğinde tutulabilir veya işlem tamamlanana veya durdurulana kadar tutulabilir. Birincisi aktarım hızı için daha iyidir, ikincisi tutarlılık için daha iyidir. İki tür kilit ve iki tür işlem (okuma/yazma) dört temel yalıtım düzeyi verir. Daha fazla bilgi için bkz. IsolationLevel.
İç içe TransactionScope nesneler kullanılırken, ortam işlemine katılmak isteyen tüm iç içe kapsamların tam olarak aynı yalıtım düzeyini kullanacak şekilde yapılandırılması gerekir. İç içe yerleştirilmiş TransactionScope bir nesne ortam işlemine katılmaya çalışırsa ancak farklı bir yalıtım düzeyi belirtirse, bir ArgumentException atılır.
COM+ ile birlikte çalışma
Yeni bir TransactionScope örneği oluşturduğunuzda, ilk olarak bir oluşturucuda EnterpriseServicesInteropOption numaralandırmasını kullanarak COM+ ile nasıl etkileşim kurulacağını belirtebilirsiniz. Bu konuda daha fazla bilgi için bkz. Enterprise Services ve COM+ İşlemleri ile Birlikte Çalışabilirlik.