Makale Özeti

COM+ hizmetlerinden faydalanabilmek için bu işlemleri (servicedcomponent'den miras, strong named assembly, com+ kataloğuna kayıt) yapmak zorunda değiliz. COM+ 1.5 sürümünün yüklü olduğu bir işletim sistemin (Windows 2003,XP) COM+ Component'i oluşturmadan COM+ servislerinden faydalanabilirsiniz.

Makale

COM+ Component'i oluşturmadan COM+ Servislerinden Faydalanmak

Hedef Kitle : Temel seviyede COM+ bilgisi olan uygulama geliştiriciler.

COM+

COM+ (com plus) işletim sistemi seviyesinde bazı hizmetler sunar ve servislerden uygulamalarımızda faydalanabilmemizi sağlar. .NET ile COM+ uygulaması geliştirebilmek için uygulama geliştiricilere sunulmuş bir namespace vardır: System.EnterpriseServices.

System.EnterpriseServices namespace'i altındaki türleri kullanarak COM+ Component'leri oluşturabilir ve bu COM+ servislerinden faydalanabiliriz.

COM+ Component'i olarak çalışmasını istediğimiz sınıflarımız için uygumamız gereken kurallar vardır.

Örneğin,

Imports System.EnterpriseServices
<JustInTimeActivation(True), Transaction(TransactionOption.Required)> _

Public
Class PakEFT
    Inherits ServicedComponent


   .....
   .....

End
Class

Yukarıda gözükmekte olan kod parçasında System.EnterpriseServices.ServicedComponent sınıfından miras (inheritance) alan bir sınıf tanımlaması gözükmektedir. Transaction ve JustInTimeActivation etiketleri ile component içerisinde transactional işlemler yapılacağı ve done biti True olduğunda nesnenin yok edilebileceği (object pooling aktif olsaydı, havuza döneceği belirleniyor) belirleniyor. (Not : Bu konular ile ilgili giriş niteliğindeki makaleleri yine sitemizde bulabilirsiniz.)

COM+ Component'i olarak belirlemek istediğimiz sınıfların ServicedComponent sınıfından miras alması zorunludur. Ayrıca bu sınıfın yer aldığı Assembly'nin Strong Named bir assembly olması gereklidir.

Başka sınıftan miras almasının zorunlu olması, strong named olması zorunluluğu gibi durumlara bakıldığında COM+ Component'i geliştirmek biraz daha zahmetlidir.

COM+ Servislerinden faydalanabilmek için bu işlemleri gerçekleştirip, COM+ Component'imizi COM+ kataloğuna kaydederek kullanırız.

COM+ 1.5

COM+ 1.5 Windows 2003 Server ve Windows XP ile beraber gelen COM+ servisleri versiyonudur. XP üzerindeki COM+ 1.5 bu makalenin konusu olan Component oluşturmadan COM+ servisleri geliştirmeyi desteklemiyordu. Windows XP SP2 ile beraber Windows XP işletim sisteminde de bu COM+ özelliğinden faydalanbiliyoruz.

COM+ Component'i Oluşturmadan Com+ Servislerinden Faydalanmak (Services Without Components)

COM+ hizmetlerinden faydalanabilmek için bu işlemleri (servicedcomponent'den miras, strong named assembly, com+ kataloğuna kayıt) yapmak zorunda değiliz. Eğer uygulamınızın çalıştığı işletim sistemi yukarıda bahsettiğim gibi COM+ 1.5 sürümüne sahip ise COM+ Component'i oluşturmadan COM+ servislerinden faydalanabilirsiniz. Aklımıza hemen ne geldi? Distributed Transactions!!

COM+ Componenti olmadan COM+ Transaction'a dahil olmak

Minik örneğimiz için bir Windows Application projesi açıp, içerisine Ornek1 adında bir class dosyası ekledikten sonra, System.EnterpriseServices.dll assembly dosyasını projemize referans olarak ekledikten sonra System.EnterpriseServices namespace'ini projemize import edelim.

Imports System.EnterpriseServices

Public
Class Ornek1

    Public Function TransactionaKatil()

        Dim config As New ServiceConfig
        config.TrackingEnabled = True 'Component Services aracı ile çalışan uygulamanın izlenebilmesini sağlar. Bu özelliği değiştirmek zorunda değiliz
        config.Transaction = TransactionOption.RequiresNew
        ServiceDomain.Enter(config)
        Dim katilabildikmi As Boolean = ContextUtil.IsInTransaction
        ServiceDomain.Leave()
        Return katilabildikmi

    End Function

End Class

ServiceConfig sınıfı

Component oluşturmadan oluşturulacak olan context ile ilgili ayarların belirlendiği türdür. Bu sınıf üzerindeki özellikler ile uygulamanın COM+ hizmetlerinden nasıl faydalanacağını belirleriz.

TrackingEnabled : Bu özellik Component Services aracı (dcomcnfg) ile çalışan uygulamanın izlenip izlenmeyeceğini belirler. Bu özelliği değiştirmek zorunda değiliz. Bu özelliği değiştirerek uygulamayı Component Services aracı ile izlemek istediğimiz için bu senaryoda özelliğe True değerini verdik.

Transaction : Bu özellik uygulamanın transactional işlemler gerçekleştirip gerçekleştirmeyeceği belirlenir. <Transaction(..)> özelliği ile verilen değerlerden birisi verilerek. Uygulamanın transaction davranışı belirlenir.

Ayrıca TrackingAppName, TrackingComponentName, TransactionTimeout gibi özellikler ile uygulamamızın başlatacağı context ile ilgili ayarlamalar yapılabilmektedir.

ServiceDomain sınıfı ile serviceconfig ile belirlenmiş olan yapılandırmaya göre uygulama COM+ servislerinden faydalanmaya başlar ve bitirebilir. ServiceDomain.Enter(cfg as ServiceConfig) ile context başlatılır. ServiceDomain.Leave() ile sonlandırılır.

Yukarıda oluşturduğumuz sınıfı test etmek için windows formu üzerine bir buton ekleyip aşağıdaki kodu yazalım.

Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
   Dim o1 As New Ornek1
   MsgBox("Durum : " & o1.TransactionaKatil)
End
Sub

Yukarıdaki örnekte transactional herhangi bir işlem gerçekleştirmeden uygulamamızı transaction içerisine dahil edebiliyor olduğumuzun testini gerçekleştirdik.

Resource üzerinde COM+ Transaction yönetiminin sağlanması

COM+ Transaction servisleri DTC (Distributed Transaction Coordinator) servisilerini kullanırlar. Fiziksel katmanda DTC'nin Two Phase Commit yönetimi sayesinde COM+ ile Distributed Transaction işlemleri gerçekleştirilebilir.

Şimdi COM+ Component'i oluşturmadan bir COM+ Servislerinden gerçekten faydalanan örnek bir uygulama gerçekleştirelim.

Dim con1 As New SqlConnection("server=.;database=northwind;user id=sa;password=;"
Dim cmd1 As SqlCommand = con1.CreateCommand
cmd1.CommandText = "UPDATE Employees SET FirstName='Birinci' WHERE EmployeeID=1"
con1.Open()
cmd1.ExecuteNonQuery()
con1.Close()
'---------
Dim con2 As New SqlConnection("server=.;database=northwind;user id=sa;password=;")
Dim cmd2 As SqlCommand = con2.CreateCommand
cmd2.CommandText = "UPDATE Employees SET FirstName='İkinci' WHERE EmployeeID=2"
con2.Open()
cmd2.ExecuteNonQuery()
con2.Close()

Yukarıdaki kodları inceleyelim, basit bir ADO.NET kodu. Birbirinden bağımsız iki SqlConnection nesnesi oluşturulup aynı DB üzerinde farklı kişilerin isimleri değiştiriliyor. Gayet basit! Senaryo icabı ikiside aynı bilgisayardaki aynı veritabanını kullanan iki ayrı kod bloğu. Farklı bilgisayarlardaki veritabanlarını Distributed Transaction'a alma işlemini ve gerekli prosedürleri bir sonraki makalemizde inceleyeceğiz.

Yukarıdaki kod parçasına göre şunu isteseydim. "Yapılan iki güncelleme işi bir bütün olsun. İki iş parçacığı bir tek bir parça olarak çalışsın." Daha basit deyimle "Ya ikisi de başarılı olarak çalıştırılsın. Ya da hiç birisi." yani işlerden birisi yapılırken hata olması ve iptal edilmesi, bütün işi iptal edilmesini sağlasın. (Unutmadan örnek kodlarımız aynı veritabanını gösterse de senaryo itibariyle bunların farklı bilgisayarlardaki veritabanı sistemleri olduğunu varsayıyoruz.) Bunun için yapmamız gereken işlem; DTC'yi devreye almak. COM+ Transaction hizmetlerinden faydalanmak.

Aşağıdaki örnek kod parçası ile ServiceConfig ve ServiceDomain sınıfları kullanılarak gerekli alt yapı oluşturulup ve uygulamamız COM+ hizmetlerinden faydanabileceği bir context'e sahip olduktan sonra bu arada  (Enter ve Leave) standart ADO.NET kodları ile DTC'nin resource olarak kullanabildiği SQL Server üzerinde işlemler yapılmıştır. Aktif context içerisinde yapılan işlemler (sql server ve msmq işlemleri gibi) DTC tarafından kontrol altına alınırlar. Bir COM+ transaction'ı içerisine dahil olurlar.

Imports System.Data.SqlClient
Imports
System.EnterpriseServices

Public Class Ornek2 

    Public Sub IkiFarkliConnectionIleIslemYap()

        Try
            Dim config As New ServiceConfig
            config.Transaction = TransactionOption.RequiresNew
            '---------- tracking ile ilgili yapılandırmalar.
            config.TrackingEnabled = True
            config.TrackingAppName = "Component Olmadan Com+ Servisleri"
            config.TrackingComponentName = "Ornek2"
            '----------
            ServiceDomain.Enter(config)  'let's go!!:)
            '---------
            Dim con1 As New SqlConnection("server=.;database=northwind;user id=sa;password=;"
            Dim cmd1 As SqlCommand = con1.CreateCommand
            cmd1.CommandText = "UPDATE Employees SET FirstName='Birinci' WHERE EmployeeID=1"
            con1.Open()
            cmd1.ExecuteNonQuery()
            con1.Close()
            '---------
            Dim con2 As New SqlConnection("server=.;database=northwind;user id=sa;password=;")            Dim cmd2 As SqlCommand = con2.CreateCommand
            cmd2.CommandText = "UPDATE Employees SET FirstName='İkinci' WHERE EmployeeID=2"
            con2.Open()
            cmd2.ExecuteNonQuery()
            con2.Close()
            '---------
            ContextUtil.SetComplete() 'işler yolunda tüm işlemleri onayla
        Catch ex As Exception
            ContextUtil.SetAbort() 'işler yolunda gitmedi transaction içindeki tüm işleri geri al
            Throw ex
        Finally
            ServiceDomain.Leave()
        End Try

    End Sub

End Class

COM+ Transaction'ının durumunu (tutarlı?) belirlemek için ContextUtil.SetComplete (done=true,consistent=true) veya ContextUtil.SetAbort (done=true,consistent=false) metodları ile işlem başarılı yada başarısız biçimde sonlandırılıyor.

Yukarıdaki sınıfı test etmek için windows formu üzerine ikinci bir buton ekleyin ve aşağıdaki kodu yazın.

Private Sub Button2_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button2.Click

        Try
            Dim o2 As New Ornek2
            o2.IkiFarkliConnectionIleIslemYap()
        Catch ex As Exception
            MsgBox(ex.Message)
        End Try

End Sub

Yukarıdaki kodu test ettiğinizde işlem başarılı olarak yapıldığında her iki kayıdında güncellendiğini göreceksiniz. COM+ Transaction'ının devrede olduğunu anlayabilmek için bir hata oluşturmanız uygun olacaktır. Örneğin FirstName sütununa (nvarchar(10) olduğu için) 10 karakterden uzun bir değer vererek bir hata oluşmasını sağlayabilirsiniz. Bu durumda yapılan iki iş parçacığından birisinde hata olduğu için bütün iş (iki iş parçacığı da) iptal edilecek, onaylanmayacaktır.

"COM+ Component'i oluşturmadan COM+ Servislerinden Faydalanmak" (Services Without Components) başlıklı makalemiz ile COM+ servislerinden faydalanmak için kullanılabileceğimiz alternatif ve pratik bir yöntemden bahsettik. Ve bu güzel özelliğin kullanımı örneklendirdik. Bu konu üzerine sonraki makalemizde, daha object oriented bir yapı ile ufak örnekler gerçekleştirip, transaction yönetiminin gerçekten "distributed" yapılmasını örneklendireceğiz.


Örnek Uygulama

Cengiz HAN
Microsoft ASP.NET MVP
cengiz@cengizhan.com

Örnek Uygulama