Hizmet İşlem Davranışı

İşlemler örneği, hizmet işlemi davranışını denetlemek için istemci eşgüdümlü bir işlemin kullanımını ve ServiceBehaviorAttribute ve OperationBehaviorAttribute ayarlarını gösterir. Bu örnek, bir hesap makinesi hizmeti uygulayan Başlarken örneğini temel alır, ancak gerçekleştirilen işlemleri bir veritabanı tablosunda sunucu günlüğü olarak tutmak ve hesap makinesi işlemleri için durumsal bir toplamı korumak amacıyla genişletilmiştir. Sunucu günlük tablosuna kalıcı yazma işlemleri, istemci eşgüdümlü işleminin sonucuna bağlıdır. İstemci işlemi tamamlanmazsa, Web hizmeti işlemi veritabanındaki güncelleştirmelerin işlenmemesini sağlar.

Not

Bu örnek için kurulum yordamı ve derleme yönergeleri bu makalenin sonunda bulunur.

Hizmetin sözleşmesi, tüm işlemlerin isteklerle birlikte bir işlemin akışını gerektirdiğini tanımlar:

[ServiceContract(Namespace = "http://Microsoft.ServiceModel.Samples",
                    SessionMode = SessionMode.Required)]
public interface ICalculator
{
    [OperationContract]
    [TransactionFlow(TransactionFlowOption.Mandatory)]
    double Add(double n);
    [OperationContract]
    [TransactionFlow(TransactionFlowOption.Mandatory)]
    double Subtract(double n);
    [OperationContract]
    [TransactionFlow(TransactionFlowOption.Mandatory)]
    double Multiply(double n);
    [OperationContract]
    [TransactionFlow(TransactionFlowOption.Mandatory)]
    double Divide(double n);
}

Gelen işlem akışını etkinleştirmek için hizmet, sistem tarafından sağlanan varsayılan wsHttpBinding ile ve transactionFlow özniteliği true olarak ayarlanmış şekilde yapılandırılır. Bu bağlama birlikte çalışabilir WSAtomicTransactionOctober2004 protokolunu kullanır:

<bindings>
  <wsHttpBinding>
    <binding name="transactionalBinding" transactionFlow="true" />
  </wsHttpBinding>
</bindings>

Hem hizmetle hem de işlemle bir bağlantı başlatdıktan sonra, istemci bu işlem kapsamında birkaç hizmet işlemine erişir ve ardından işlemi tamamlar ve bağlantıyı kapatır:

// Create a client
CalculatorClient client = new CalculatorClient();

// Create a transaction scope with the default isolation level of Serializable
using (TransactionScope tx = new TransactionScope())
{
    Console.WriteLine("Starting transaction");

    // Call the Add service operation.
    double value = 100.00D;
    Console.WriteLine("  Adding {0}, running total={1}",
                                        value, client.Add(value));

    // Call the Subtract service operation.
    value = 45.00D;
    Console.WriteLine("  Subtracting {0}, running total={1}",
                                        value, client.Subtract(value));

    // Call the Multiply service operation.
    value = 9.00D;
    Console.WriteLine("  Multiplying by {0}, running total={1}",
                                        value, client.Multiply(value));

    // Call the Divide service operation.
    value = 15.00D;
    Console.WriteLine("  Dividing by {0}, running total={1}",
                                        value, client.Divide(value));

    Console.WriteLine("  Completing transaction");
    tx.Complete();
}

Console.WriteLine("Transaction committed");

// Closing the client gracefully closes the connection and cleans up resources
client.Close();

Hizmette, hizmet işlemi davranışını etkileyen üç öznitelik vardır ve bunu aşağıdaki yollarla yapar:

  • ServiceBehaviorAttribute üzerinde:

    • özelliği, TransactionTimeout bir işlemin tamamlanması gereken süreyi belirtir. Bu örnekte 30 saniye olarak ayarlanmıştır.

    • özelliği, TransactionIsolationLevel hizmetin desteklediği yalıtım düzeyini belirtir. Bu, istemcinin yalıtım düzeyiyle eşleşmesi için gereklidir.

    • özelliği, ReleaseServiceInstanceOnTransactionComplete bir işlem tamamlandığında hizmet örneğinin geri dönüştürülip geri dönüştürülmeyeceğini belirtir. Bunu false olarak ayarlayarak, hizmet işlem istekleri boyunca aynı hizmet örneğini tutar. Bu, devam eden toplamı korumak için gereklidir. olarak trueayarlanırsa, tamamlanan her eylemden sonra yeni bir örnek oluşturulur.

    • özelliği, TransactionAutoCompleteOnSessionClose oturum kapatıldığında bekleyen işlemlerin tamamlanıp tamamlanmayacağını belirtir. İşlemleri, ya OperationBehaviorAttribute.TransactionAutoComplete özelliğini true olarak ayarlayarak ya da işlemlerin tamamlanması için OperationContext.SetTransactionComplete() yöntemine açıkça bir çağrı yaparak false olarak ayarlamak gerekir. Bu örnekte her iki yaklaşım da gösterilmektedir.

  • ServiceContractAttribute üzerinde:

    • SessionMode özelliği, hizmetin uygun istekleri bir mantıksal oturumla ilişkilendirip ilişkilendirmediğini belirtir. Bu hizmet OperationBehaviorAttribute TransactionAutoComplete özelliğinin (Çarpma ve Bölme) olarak ayarlandığı işlemleri içerdiğinden false belirtilmelidir SessionMode.Required . Örneğin, Çarpma işlemi işlemesini tamamlamaz ve bunun yerine SetTransactionComplete yöntemi ile tamamlanması için daha sonraki bir Bölme işlemine dayanır; servisin bu işlemlerin aynı oturumda gerçekleştiğini belirleyebilmesi gerekir.
  • OperationBehaviorAttribute üzerinde:

    • TransactionScopeRequired özelliği, operasyonun eylemlerinin işlem kapsamı içinde yürütülüp yürütülmeyeceğini belirtir. Bu örnekteki tüm işlem için true olarak ayarlanır ve istemci işlemini tüm işlemlere taşıdığından, eylemler bu istemci işlemi kapsamına girer.

    • özelliği, TransactionAutoComplete işlenemeyen özel durumlar oluşmazsa yöntemin yürütüldiği işlemin otomatik olarak tamamlanıp tamamlanmayacağını belirtir. Daha önce açıklandığı gibi, bu değer Ekle ve Çıkar işlemleri için true, Çarpma ve Bölme işlemleri için false olarak ayarlanır. Ekle ve Çıkar işlemleri eylemlerini otomatik olarak tamamlar, Böl işlemi ise SetTransactionComplete yöntemine yapılan açık bir çağrıyla eylemlerini tamamlar. Çarpma işlemi eylemlerini tamamlamaz; bunun yerine, eylemleri tamamlamak için daha sonra yapılan, örneğin Bölme gibi, bir çağrıya ihtiyaç duyar ve buna dayanır.

Öznitelikli hizmet uygulaması aşağıdaki gibidir:

[ServiceBehavior(
    TransactionIsolationLevel = System.Transactions.IsolationLevel.Serializable,
    TransactionTimeout = "00:00:30",
    ReleaseServiceInstanceOnTransactionComplete = false,
    TransactionAutoCompleteOnSessionClose = false)]
public class CalculatorService : ICalculator
{
    double runningTotal;

    public CalculatorService()
    {
        Console.WriteLine("Creating new service instance...");
    }

    [OperationBehavior(TransactionScopeRequired = true, TransactionAutoComplete = true)]
    public double Add(double n)
    {
        RecordToLog(String.Format(CultureInfo.CurrentCulture, "Adding {0} to {1}", n, runningTotal));
        runningTotal = runningTotal + n;
        return runningTotal;
    }

    [OperationBehavior(TransactionScopeRequired = true, TransactionAutoComplete = true)]
    public double Subtract(double n)
    {
        RecordToLog(String.Format(CultureInfo.CurrentCulture, "Subtracting {0} from {1}", n, runningTotal));
        runningTotal = runningTotal - n;
        return runningTotal;
    }

    [OperationBehavior(TransactionScopeRequired = true, TransactionAutoComplete = false)]
    public double Multiply(double n)
    {
        RecordToLog(String.Format(CultureInfo.CurrentCulture, "Multiplying {0} by {1}", runningTotal, n));
        runningTotal = runningTotal * n;
        return runningTotal;
    }

    [OperationBehavior(TransactionScopeRequired = true, TransactionAutoComplete = false)]
    public double Divide(double n)
    {
        RecordToLog(String.Format(CultureInfo.CurrentCulture, "Dividing {0} by {1}", runningTotal, n));
        runningTotal = runningTotal / n;
        OperationContext.Current.SetTransactionComplete();
        return runningTotal;
    }

    // Logging method omitted for brevity
}

Örneği çalıştırdığınızda, işlem istekleri ve yanıtları istemci konsolu penceresinde görüntülenir. İstemciyi kapatmak için istemci penceresinde ENTER tuşuna basın.

Starting transaction
Performing calculations...
  Adding 100, running total=100
  Subtracting 45, running total=55
  Multiplying by 9, running total=495
  Dividing by 15, running total=33
  Completing transaction
Transaction committed
Press <ENTER> to terminate client.

Hizmet işlemi isteklerinin günlüğe kaydedilmesi hizmetin konsol penceresinde görüntülenir. İstemciyi kapatmak için istemci penceresinde ENTER tuşuna basın.

Press <ENTER> to terminate service.
Creating new service instance...
  Writing row 1 to database: Adding 100 to 0
  Writing row 2 to database: Subtracting 45 from 100
  Writing row 3 to database: Multiplying 55 by 9
  Writing row 4 to database: Dividing 495 by 15

Hizmetin, hesaplamaların toplamın sürekli hesabını tutmanın yanı sıra, bu örnek için örneklerin oluşturulmasını rapor ettiğini ve işlem isteklerini bir veritabanına günlüğe kaydettiğini unutmayın. Tüm istekler istemcinin işlemine bağlı olduğu için, bu işlemin tamamlanamaması tüm veritabanı işlemlerinin geri döndürülmesine neden olur. Bu, çeşitli yollarla gösterilebilir:

  • İstemcinin () çağrısına tx.Completeaçıklama ekleyin ve yeniden çalıştırın; bu, istemcinin işlemini tamamlamadan işlem kapsamından çıkmasıyla sonuçlanıyor.

  • Divide hizmeti işlemine yapılan çağrıyı yorum satırı olarak işaretleyin - Bu, sonuç olarak Çarpma işlemi tarafından başlatılan eylemin tamamlanmasını engeller ve böylece istemcinin işlemi de tamamlanamaz.

  • İstemcinin işlem kapsamının herhangi bir yerinde yakalanmamış bir istisna fırlatın; bu da benzer şekilde istemcinin işlemini tamamlamasını engeller.

Bunlardan herhangi birinin sonucu, bu kapsamda gerçekleştirilen işlemlerin hiçbirinin işlenmemesi ve veritabanında kalıcı olan satır sayısının artmamasıdır.

Not

Derleme işleminin bir parçası olarak veritabanı dosyası bin klasörüne kopyalanır. Visual Studio projesine dahil edilen dosya yerine günlükte kalıcı olan satırları gözlemlemek için veritabanı dosyasının bu kopyasına bakmanız gerekir.

Örneği ayarlamak, derlemek ve çalıştırmak için

  1. SQL Server 2005 Express Sürüm veya SQL Server 2005 yüklediğinizden emin olun. Hizmetin App.config dosyasında veritabanı connectionString ayarlanabilir veya appSettings değeri usingSqlolarak ayarlanarak veritabanı etkileşimleri false devre dışı bırakılabilir.

  2. Çözümün C# veya Visual Basic .NET sürümünü oluşturmak için Windows Communication Foundation Örnekleri Oluşturma başlığındaki yönergeleri izleyin.

  3. Örneği tek veya makineler arası bir yapılandırmada çalıştırmak için Windows Communication Foundation Örneklerini Çalıştırma başlığındaki yönergeleri izleyin.

Örneği makineler arasında çalıştırırsanız, ağ işlem akışını etkinleştirmek için Microsoft Dağıtılmış İşlem Düzenleyicisi'ni (MSDTC) yapılandırmanız ve Windows Communication Foundation (WCF) işlemleri ağ desteğini etkinleştirmek için WsatConfig.exe aracını kullanmanız gerekir.

Microsoft Dağıtılmış İşlem Düzenleyicisi'ni (MSDTC) örneği makineler arasında çalıştırmayı destekleyecek şekilde yapılandırmak için

  1. Hizmet makinesinde MSDTC'yi gelen ağ işlemlerine izin verecek şekilde yapılandırın.

    1. Başlat menüsünden Denetim Masası,Yönetim Araçları'na ve ardından Bileşen Hizmetleri'ne gidin.

    2. Bilgisayarım'a sağ tıklayın ve Özellikler'i seçin.

    3. MSDTC sekmesinde Güvenlik Yapılandırması'na tıklayın.

    4. Ağ DTC Erişimini ve Gelenlere İzin Ver'i denetleyin.

    5. MS DTC hizmetini yeniden başlatmak için Evet'e ve ardından Tamam'a tıklayın.

    6. Tamam’a tıklayarak iletişim kutusunu kapatın.

  2. Hizmet makinesinde ve istemci makinede, Windows Güvenlik Duvarı'nı Microsoft Dağıtılmış İşlem Düzenleyicisi'ni (MSDTC) hariç uygulamalar listesine içerecek şekilde yapılandırın:

    1. Denetim Masası'den Windows Güvenlik Duvarı uygulamasını çalıştırın.

    2. Özel Durumlar sekmesinde Program Ekle'ye tıklayın.

    3. C:\WINDOWS\System32 klasörüne gidin.

    4. Msdtc.exe seçin ve Aç'a tıklayın.

    5. Program Ekle iletişim kutusunu kapatmak için Tamam'a tıklayın ve Windows Güvenlik Duvarı'nı kapatmak için yeniden Tamam'a tıklayın.

  3. İstemci makinesinde MSDTC'yi giden ağ işlemlerine izin verecek şekilde yapılandırın:

    1. Başlat menüsünden Denetim Masası,Yönetim Araçları'na ve ardından Bileşen Hizmetleri'ne gidin.

    2. Bilgisayarım'a sağ tıklayın ve Özellikler'i seçin.

    3. MSDTC sekmesinde Güvenlik Yapılandırması'na tıklayın.

    4. Ağ DTC Erişimi'ni ve Gidene İzin Ver'i denetleyin.

    5. MS DTC hizmetini yeniden başlatmak için Evet'e ve ardından Tamam'a tıklayın.

    6. Tamam’a tıklayarak iletişim kutusunu kapatın.