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.
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
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.
Cengiz HAN Microsoft ASP.NET MVP cengiz@cengizhan.com