• Anasayfa
  • Hakkımızda
  • Etkinlikler
  • Destek Verin
  • Site Haritası
  • Giriş Yap
  • Üye Ol
  • Facebook
  • Twitter
  • RSS
Yazılım Dilleri
  • Soru - Cevap
  • EĞİTİM SETİ
  • KATEGORİ
  • DUYURU
  • TEKNOLOJİ HABERLERİ

Son Sorular

  • 23.04.2016 00:55:33C programlama 2 oyun
  • 20.04.2016 16:34:41Local Database
  • 15.04.2016 14:26:15Fatura kayıt işlemi
  • 21.03.2016 01:55:30C# problem

Popüler Sorular

  • 27.05.2012 05:49:50Asp.Net ile Date time alana veri ekleyemiiyorum ?
  • 2.04.2012 00:45:18.exe uzantılı dosya için dijital imza nerde nasıl alınır.
  • 12.05.2012 08:44:49Acil Yardım
  • 27.05.2012 13:46:51veri tabanı bağlantısı
  • .Net Framework
  • 8085 Assembly
  • Active Directory
  • ADO.NET
  • Android
  • Apple IOS
  • Arduino
  • ASP.NET
  • ASP.NET MVC
  • Blackberry
  • C#.Net
  • C++
  • CCG Framework
  • CISCO
  • CSS
  • Diğer
  • Dreamweaver
  • Entity Framework
  • Exchange Server
  • Gömülü Sistemler
  • GSM Programlama
  • Güncel
  • Güvenlik
  • HTML5
  • Java
  • Javascript / JQuery
  • Jira
  • Kariyer ve İş Yaşamı
  • LINQ
  • LibreOffice
  • Linux
  • Matlab
  • Microsoft Dynamics CRM
  • Mobil Uygulama Geliştirme
  • MySQL
  • NoSQL
  • Oracle
  • OWIN
  • PFSense
  • PHP
  • Powershell
  • Python
  • Sanallastirma
  • SAP-ABAP
  • SCOM 2012
  • SEO
  • Sharepoint 2010
  • Sharepoint 2013
  • Silverlight
  • Sistem Analiz ve Tasarımı
  • SQL Server
  • Symantec
  • TFS
  • T-SQL
  • Ubuntu
  • VB.NET
  • Veritabanı Yönetim Sistemleri
  • Visual Studio
  • VMware
  • WCF
  • Web Hosting
  • Windows 8
  • Windows Azure
  • Windows Phone 7.1
  • Windows Phone 8
  • Windows Server
  • Wordpress
  • WPF
  • Xamarin
  • XNA
  • Yazılım Mühendisliği
  • Yöneylem Araştırması
  • ASP.NET MVC
  • Entity Framework
  • Javascript / JQuery
  • LINQ
  • PHP

Son Duyurular

IPhone 6 ve IPhone 6 Plus Teknik Özellikleri ve Fiyatı

IPhone 6 ve IPhone 6 Plus Teknik Özellikleri ve Fiyatı

DELL'in Yeni Projesi: USB Bilgisayar (Project Ophelia)

DELL'in Yeni Projesi: USB Bilgisayar (Project Ophelia)

Windows Phone Youtube Uygulaması Google ve Microsoft ile Yeniden Yapılıyor

Windows Phone Youtube Uygulaması Google ve Microsoft ile Yeniden Yapılıyor

Android ve Apple IOS Telefonlar için Blackberry Messenger (BBM)

Android ve Apple IOS Telefonlar için Blackberry Messenger (BBM)

Nokia Lumia 925 Teknik Özellikleri, Lumia 928 ve 920 ile Karşılaştırması

Nokia Lumia 925 Teknik Özellikleri, Lumia 928 ve 920 ile Karşılaştırması

LG Optimus G Pro Özellikleri ve Gözle Video Oynatma Teknolojisi

LG Optimus G Pro Özellikleri ve Gözle Video Oynatma Teknolojisi

Workflow Foundation, Oracle, WCF ve TransactionScope

Workflow Foundation, Oracle, WCF ve TransactionScope

03.02.2013

Yazar: Burak Selim Şenyurt (Google+)

Kategori: WCF

4866

Proof-of-Concept-Prototypes-Dont-Have-to-Be-as-Complicated-as-This[Örnek Visual Studio 2010, .Net Framework 4.0 tabanlidir]

Merhaba Arkadaslar,

Yandaki fotografta görülen bulusa baktiginizda aslinda gerçekten bu pilotun o koca pervaneler ile uçup uçamayacagina pek kanaat getiremiyoruz öyle degil mi?

Sonuçta en azindan kagit üstünde ve teorik olarak da bu tip bir uçus aracinin çalisacaginin ispat edilmesi ve sonrasinda pratikteki kullanimi için teste çikilmasi beklenir(Tabi buna cesaret edecek de bir pilotun olmasi gerekir)

Bir dostumuzun söyledigi üzere "tasarlanan her uçak uçmus ama her yazilim çalismamistir" Winking smile

Bir baska deyisle yazilim tarafinda bir seylerin ispatini yaparken bir uçagi uçuracakmis gibi düsünerek hareket etmeyiz genelde. Istesek de edemiyoruz sanirim. Yine de elimizden geldigince titiz çalismamiz da yarar var. Öyleyse gelelim bu günün konusuna.

Geçtigimiz günlerde Workflow Foundation tabanli bir uygulama içerisinde Transaction Scope kullanimina ihtiyacim oldu. Transaction' a dahil olan islemler Oracle tablolari üzerinde gerçeklestirilecekti. Senaryoyu zorlastiran noktalardan birisi ise, akis içerisinde harici bir WCF servis çagrisinin yapilacak olmasiydi. Nitekim söz konusu WCF servisi içerisindeki operasyonda da, yine Oracle veritabani üzerinde yapilmasi planlanan Transactional bir islem söz konusuydu.

Dolayisiyla Oracle' in ve WCF servisinin isin içerisinde yer aldigi bir Workflow senaryosunda, TransactionScope bileseninin ise yarayip yaramadiginin arastirilmasi ve gerekli ispatlarin yapilmasi gerekmekteydi. Bir baska deyisle bir POC(Proof Of Concept) çalismasi ile karsi karsiyaydik. Ben de Visual Studio 2010 un basina oturdum ve yola koyuldum.

Senaryoda kendi olusturdugum iki Oracle tablosu söz konusu idi. Bu tablolarin içerdigi alanlarin çok fazla önemi yoktu aslinda. Account ve Branch olarak adlandirdigim tablolar üzerinde iki basit Insert islemi gerçeklestirecektim. Buna ek olarak bir de WCF servisi söz konusu olmaliydi. Ilgili WCF servisi de yine benzer bir Insert islemi gerçeklestirilmek üzere tasarlanmaliydi.

Teorik olarak Workflow Activity' si içerisinde kullanilacak TransactionScope Component' i servis tarafina Transaction' i aktarabilmeliydi. Tam bu noktada Distributed Transaction Coordinator servisinin de islevselligi söz konusuydu. Elbette servis tarafinin da, Transaction akisina izin verecek sekilde tesis edilmesi sartti.

Bu noktada özellikle Binding tipinin Transaction Flow' a destek veriyor olmasi önemlidir. Nitekim varsayilan baglayici tip olan BasicHttpBinding, istemciden gelen Transaction akisina izin vermez. Ama örnegin wsHttpBinding buna olanak tanir.

Dilerseniz ise ilk olarak bu WCF servisini gelistirerek baslayalim. Servisimize ait basit kod içerigi asagidaki gibidir.

using System.ServiceModel;

namespace CRUDer
{
    [ServiceContract]
    public interface IAccountService
    {
        [OperationContract]
        [TransactionFlow(TransactionFlowOption.Mandatory)]
        int DoWork(int AccountId,string Name,string Surname);
    }
}

Sözlesme tipi içerisindeki en önemli nokta TransactionFlow niteliginin kullanilmasi ve Mandatory degerinin verilmesidir. Bu nitelik Allowed, NotAllowed seklinde iki farkli deger daha alabilir. Mandatory, istemci tarafinda bir Transaction Scope baslatilma zorunlulugunu ifade etmektedir. Nitekim operasyon içerisindeki islemin bir Transaction Scope' a dahil olmasi sarttir.

using System.Configuration;
using System.ServiceModel;
using System.Transactions;
using Oracle.DataAccess.Client;

namespace CRUDer
{
    //[ServiceBehavior(TransactionIsolationLevel=IsolationLevel.Serializable)]
    public class AccountService
        : IAccountService
    {
       [OperationBehavior(TransactionScopeRequired=true, TransactionAutoComplete=true)]
        public int DoWork(int AccountId, string Name, string Surname)
        {
            int result = -1;

            var currentTransaction=Transaction.Current;
            using (OracleConnection conn = new OracleConnection(ConfigurationManager.ConnectionStrings["ConStr"].ConnectionString))
            {
                using (OracleCommand command = new OracleCommand("INSERT INTO ACCOUNT (ACCOUNTID,NAME,SURNAME) VALUES (:pACCOUNTID,:pNAME,:pSURNAME)", conn))
                {
                    command.Parameters.Add(":pACCOUNTID",AccountId);
                    command.Parameters.Add(":pNAME", Name);
                    command.Parameters.Add(":pSURNAME", Surname);

                    conn.Open();
                    result = command.ExecuteNonQuery();
                }
            }

            return result;
        }
    }
}

Servisin asil is yapan kodlarinda yine dikkat çekici ve önemli olan nokta OperationBehavior niteligi ile atanan özellik(Property) degerleridir. Operasyonun bir TransactionScope gerektirdigi ve ayrica unhandled exception olusmasi halinde operasyona ait transaction örneginin otomatik olarak tamamlanip tamamlanmayacagi belirtilmektedir.

Servis tarafinda System.Transactions assembly' inin referans edilmesi unutulmamalidir. Ayrica hem servis hem de istemci tarafi Oracle fonksiyonellikleri için ODP.Net' e(Oracle DataProvider for .Net) ait assembly' lari kullanmaktadir. Dolayisiyla Oracle.DataAccess assembly’ inin uygun olan versiyonunun referans edilmelidir.

Servis tarafindaki config dosyasinin içerigi de oldukça önemlidir. Daha önceden de belirttigimiz üzere Binding tipi, Transaction akisina izin verir nitelikte olmalidir. Ancak buna ek olarak Transaction akisina izin verileceginin de konfigurasyon dosyasi içerisinde belirtilmesi sarttir. Çünkü varsayilan olarak Transaction akisi etkin degildir.

<?xml version="1.0"?>
<configuration>
    <connectionStrings>
        <add name="ConStr" connectionString="User Id=bir kullanici adi;Password=bir sifre;Data Source=oracle veri kaynagi" providerName="Oracle.DataAccess.Client"/>
    </connectionStrings>
  <system.serviceModel>
    <services>
      <service name="CRUDer.AccountService">
        <endpoint address="http://localhost:35662/AccountService.svc"
          binding="wsHttpBinding" bindingConfiguration="wsB" contract="CRUDer.IAccountService" />
      </service>
    </services>
      <bindings>
          <wsHttpBinding>
              <binding transactionFlow="true" name="wsB"/>
          </wsHttpBinding>
      </bindings>
    <behaviors>
      <serviceBehaviors>
        <behavior name="">
          <serviceMetadata httpGetEnabled="true"/>
          <serviceDebug includeExceptionDetailInFaults="true"/>
        </behavior>
      </serviceBehaviors>
    </behaviors>
    <serviceHostingEnvironment multipleSiteBindingsEnabled="false"/>
  </system.serviceModel>
  <system.web>
    <compilation debug="true"/>
  </system.web>
</configuration>

Dikkat edilecegi üzere wsHttpBinding elementi içerisinde yer alan binding alt elementinin transactionFlow niteliginin degeri true olarak set edilmistir. Servis tarafinda yapilmasi gerekenler aslinda bu kadardir. Öyleyse Workflow tasarimina baslayabiliriz. Workflow Console Application olarak tasarlanan uygulamamizda çalisma zamanini izleyebilmek için basit de bir Tracker tipine yer verilmektedir. Bu tipin içerigi asagidaki gibidir.

using System;
using System.Activities.Tracking;
using System.Collections.Generic;
using System.Text;

namespace HowToTransaction
{
    public class CustomTracker
        : TrackingParticipant
    {
        protected override void Track(TrackingRecord record, TimeSpan timeout)
        {
            WorkflowInstanceRecord instanceRecord = record as WorkflowInstanceRecord;
            if (instanceRecord != null)
                Console.WriteLine(instanceRecord.ToString());

            ActivityStateRecord activity = record as ActivityStateRecord;
            if (activity != null)
            {               
                var variables = activity.Variables;
                StringBuilder builder = new StringBuilder();
                if (variables.Count > 0)
                {
                    builder.AppendLine(" Variables:");
                    foreach (KeyValuePair<string, object> variable in variables)
                    {
                        builder.AppendLine(String.Format(" {0} Value: [{1}]", variable.Key, variable.Value));
                    }
                }
                Console.WriteLine(
                    String.Format(" Activity: {0} State: {1} {2}",
                    activity.Activity.Name
                    , activity.State                   
                    , builder.ToString())
                    );
            }
        }
    }
}

Tracker sinifi içerisinde hem Workflow Actvitiy' si hem de içeride yürümekte olan Activity örneklerinin çalismalarinin izlenmesi islemi gerçeklestirilmektedir. Bu, TrackingRecord tipinden olan parametrenin WorkflowInstanceRecord ve ActivityStateRecord nesne örneklerine dönüstürülmesi ile gerçeklestirilmektedir. Tracker tipi disinda Account ve Branch tablolarina insert islemi yapan iki Code Activiy bileseni de bulunmaktadir. Söz konusu Activity bilesenlerinin kodlari asagidaki gibidir.

Account insert islemini üstlenen Activity,

namespace HowToTransaction
{
    using System.Activities;
    using System.Configuration;
    using Oracle.DataAccess.Client;

    public class InsertAccountActivity
        :CodeActivity
    {
        public InArgument<int> AccountId { get; set; }
        public InArgument<string> Name { get; set; }
        public InArgument<string> Surname { get; set; }
        public OutArgument<int> ExecuteNonQueryResult { get; set; }

        protected override void Execute(CodeActivityContext context)
        {
            using (OracleConnection conn = new OracleConnection(ConfigurationManager.ConnectionStrings["ConStr"].ConnectionString))
            {
                using (OracleCommand command = new OracleCommand("INSERT INTO ACCOUNT (ACCOUNTID,NAME,SURNAME) VALUES (:pACCOUNTID,:pNAME,:pSURNAME)", conn))
                {
                    command.Parameters.Add(":pACCOUNTID",context.GetValue(AccountId));
                    command.Parameters.Add(":pNAME",context.GetValue(Name));
                    command.Parameters.Add(":pSURNAME",context.GetValue(Surname));

                    conn.Open();
                    int result=command.ExecuteNonQuery();
                    context.SetValue(ExecuteNonQueryResult, result);
                }
            }
        }
    }
}

ve Branch insert islemini üstlenen Code Activity

namespace HowToTransaction
{
    using System.Activities;
    using System.Configuration;
    using Oracle.DataAccess.Client;
    using System;

    public class InsertBranchActivity
        :CodeActivity
    {
        public InArgument<int> BranchId { get; set; }
        public InArgument<string> Title { get; set; }
        public InArgument<int> Code { get; set; }
        public OutArgument<int> ExecuteNonQueryResult { get; set; }

        protected override void Execute(CodeActivityContext context)
        {
            using (OracleConnection conn = new OracleConnection(ConfigurationManager.ConnectionStrings["ConStr"].ConnectionString))
            {
                using (OracleCommand command = new OracleCommand("INSERT INTO BRANCH (BRANCHID,TITLE,CODE) VALUES (:pBRANCHD,:pTITLE,:pCODE)", conn))
                {
                    command.Parameters.Add(":pBRANCHID",context.GetValue(BranchId));
                    command.Parameters.Add(":pTITLE",context.GetValue(Title));
                    command.Parameters.Add(":pCODE",context.GetValue(Code));

                    conn.Open();
                    int result = command.ExecuteNonQuery();
                    context.SetValue(ExecuteNonQueryResult, result);
                   //throw new Exception("Some error");
                }
            }
        }
    }
}

Burada yorum satiri olarak birakilmis kisim daha sonradan yapilacak testler sirasinda açilacak ve Transaction Scope' un çalismasi izlenecektir.

Gelelim test amaçli kullanacagimiz Workflow Activity içerigine.

Workflow Foundation, Oracle, WCF ve TransactionScope

FlowChart seklinde tasarladigimiz akisin içerisindeki en kritik yer TryCatch bilesenin içerisidir.

Workflow Foundation, Oracle, WCF ve TransactionScope

Try blogundan TransactionScope bileseni altinda sirasiyla Account Insert islemi, DoWork ile WCF servis çagrisi ve tekrar Branch Insert islemi gerçeklestirilmektedir.

WCF servisinin Workflow uygulamasina Add Service Reference ile eklenmesi sonrasi Component sekmesine çikan aktivite bileseni kullanilmaktadir(DoWork bileseni)

Workflow Foundation, Oracle, WCF ve TransactionScope

Workflow un XAML(eXtensibleApplicationMarkupLanguage) içerigi asagidaki gibidir. Burada, kullanilan variable’ lar daha net bir sekilde görülebilmektedir.

<Activity mc:Ignorable="sads sap" x:Class="HowToTransaction.Workflow1" sap:VirtualizedContainerService.HintSize="654,676" mva:VisualBasic.Settings="Assembly references and imported namespaces for internal implementation"
xmlns="http://schemas.microsoft.com/netfx/2009/xaml/activities"
xmlns:av="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:hc="clr-namespace:HowToTransaction.CRUDerReference"
xmlns:local="clr-namespace:HowToTransaction"
xmlns:local1="clr-namespace:HowToTransaction.CRUDerReference.Activities"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:mv="clr-namespace:Microsoft.VisualBasic;assembly=System"
xmlns:mva="clr-namespace:Microsoft.VisualBasic.Activities;assembly=System.Activities"
xmlns:p="http://schemas.microsoft.com/netfx/2009/xaml/servicemodel"
xmlns:s="clr-namespace:System;assembly=mscorlib"
xmlns:s1="clr-namespace:System;assembly=System"
xmlns:s2="clr-namespace:System;assembly=System.Xml"
xmlns:s3="clr-namespace:System;assembly=System.Core"
xmlns:s4="clr-namespace:System;assembly=System.ServiceModel"
xmlns:sa="clr-namespace:System.Activities;assembly=System.Activities"
xmlns:sad="clr-namespace:System.Activities.Debugger;assembly=System.Activities"
xmlns:sads="http://schemas.microsoft.com/netfx/2010/xaml/activities/debugger"
xmlns:sap="http://schemas.microsoft.com/netfx/2009/xaml/activities/presentation"
xmlns:scg="clr-namespace:System.Collections.Generic;assembly=System"
xmlns:scg1="clr-namespace:System.Collections.Generic;assembly=System.ServiceModel"
xmlns:scg2="clr-namespace:System.Collections.Generic;assembly=System.Core"
xmlns:scg3="clr-namespace:System.Collections.Generic;assembly=mscorlib"
xmlns:sd="clr-namespace:System.Data;assembly=System.Data"
xmlns:sl="clr-namespace:System.Linq;assembly=System.Core"
xmlns:st="clr-namespace:System.Text;assembly=mscorlib"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
  <Flowchart sad:XamlDebuggerXmlReader.FileName="d:\users\bsenyurt\documents\visual studio 2010\Projects\Windows Phone\HowToTransaction\HowToTransaction\Workflow1.xaml" sap:VirtualizedContainerService.HintSize="614,636">
    <sap:WorkflowViewStateService.ViewState>
      <scg3:Dictionary x:TypeArguments="x:String, x:Object">
        <x:Boolean x:Key="IsExpanded">False</x:Boolean>
        <av:Point x:Key="ShapeLocation">270,2.5</av:Point>
        <av:Size x:Key="ShapeSize">60,75</av:Size>
        <av:PointCollection x:Key="ConnectorLocation">300,77.5 300,139.5</av:PointCollection>
      </scg3:Dictionary>
    </sap:WorkflowViewStateService.ViewState>
    <Flowchart.StartNode>
      <FlowStep x:Name="__ReferenceID0">
        <sap:WorkflowViewStateService.ViewState>
          <scg3:Dictionary x:TypeArguments="x:String, x:Object">
            <av:Point x:Key="ShapeLocation">194.5,139.5</av:Point>
            <av:Size x:Key="ShapeSize">211,59</av:Size>
            <av:PointCollection x:Key="ConnectorLocation">300,198.5 300,228.5 160,228.5 160,245.5</av:PointCollection>
          </scg3:Dictionary>
        </sap:WorkflowViewStateService.ViewState>
        <WriteLine sap:VirtualizedContainerService.HintSize="211,59" Text="Account ve Branch tablolari için Insert islemleri basliyor">
          <sap:WorkflowViewStateService.ViewState>
            <scg3:Dictionary x:TypeArguments="x:String, x:Object">
              <x:Boolean x:Key="IsExpanded">True</x:Boolean>
            </scg3:Dictionary>
          </sap:WorkflowViewStateService.ViewState>
        </WriteLine>
        <FlowStep.Next>
          <FlowStep x:Name="__ReferenceID2">
            <sap:WorkflowViewStateService.ViewState>
              <scg3:Dictionary x:TypeArguments="x:String, x:Object">
                <av:Point x:Key="ShapeLocation">60,245.5</av:Point>
                <av:Size x:Key="ShapeSize">200,49</av:Size>
                <av:PointCollection x:Key="ConnectorLocation">160,294.5 160,324.5 290,324.5 290,340.5</av:PointCollection>
              </scg3:Dictionary>
            </sap:WorkflowViewStateService.ViewState>
            <TryCatch sap:VirtualizedContainerService.HintSize="418,529">
              <TryCatch.Variables>
                <Variable x:TypeArguments="x:Int32" Name="ServiceCallResult" />
              </TryCatch.Variables>
              <sap:WorkflowViewStateService.ViewState>
                <scg3:Dictionary x:TypeArguments="x:String, x:Object">
                  <x:Boolean x:Key="IsExpanded">True</x:Boolean>
                </scg3:Dictionary>
              </sap:WorkflowViewStateService.ViewState>
              <TryCatch.Try>
                <TransactionScope AbortInstanceOnTransactionFailure="False" sap:VirtualizedContainerService.HintSize="258,351">
                  <sap:WorkflowViewStateService.ViewState>
                    <scg3:Dictionary x:TypeArguments="x:String, x:Object">
                      <x:Boolean x:Key="IsExpanded">True</x:Boolean>
                    </scg3:Dictionary>
                  </sap:WorkflowViewStateService.ViewState>
                  <Sequence sap:VirtualizedContainerService.HintSize="222,270">
                    <sap:WorkflowViewStateService.ViewState>
                      <scg3:Dictionary x:TypeArguments="x:String, x:Object">
                        <x:Boolean x:Key="IsExpanded">True</x:Boolean>
                      </scg3:Dictionary>
                    </sap:WorkflowViewStateService.ViewState>
                    <local:InsertAccountActivity ExecuteNonQueryResult="{x:Null}" AccountId="2" sap:VirtualizedContainerService.HintSize="200,22" Name="Delinin" Surname="Biri">
                      <sap:WorkflowViewStateService.ViewState>
                        <scg3:Dictionary x:TypeArguments="x:String, x:Object">
                          <x:Boolean x:Key="IsExpanded">True</x:Boolean>
                        </scg3:Dictionary>
                      </sap:WorkflowViewStateService.ViewState>
                    </local:InsertAccountActivity>
                    <local1:DoWork AccountId="99" DoWorkResult="[ServiceCallResult]" EndpointConfigurationName="WSHttpBinding_IAccountService" sap:VirtualizedContainerService.HintSize="200,22" Name="Maykil" mva:VisualBasic.Settings="Assembly references and imported namespaces serialized as XML namespaces" Surname="Cordin" />
                    <local:InsertBranchActivity ExecuteNonQueryResult="{x:Null}" BranchId="34" Code="4" sap:VirtualizedContainerService.HintSize="200,22" Title="germany">
                      <sap:WorkflowViewStateService.ViewState>
                        <scg3:Dictionary x:TypeArguments="x:String, x:Object">
                          <x:Boolean x:Key="IsExpanded">True</x:Boolean>
                        </scg3:Dictionary>
                      </sap:WorkflowViewStateService.ViewState>
                    </local:InsertBranchActivity>
                  </Sequence>
                </TransactionScope>
              </TryCatch.Try>
              <TryCatch.Catches>
                <Catch x:TypeArguments="s:Exception" sap:VirtualizedContainerService.HintSize="404,20">
                  <sap:WorkflowViewStateService.ViewState>
                    <scg3:Dictionary x:TypeArguments="x:String, x:Object">
                      <x:Boolean x:Key="IsExpanded">False</x:Boolean>
                      <x:Boolean x:Key="IsPinned">False</x:Boolean>
                    </scg3:Dictionary>
                  </sap:WorkflowViewStateService.ViewState>
                  <ActivityAction x:TypeArguments="s:Exception">
                    <ActivityAction.Argument>
                      <DelegateInArgument x:TypeArguments="s:Exception" Name="exception" />
                    </ActivityAction.Argument>
                    <WriteLine sap:VirtualizedContainerService.HintSize="211,59" Text="[exception.Message]" />
                  </ActivityAction>
                </Catch>
              </TryCatch.Catches>
            </TryCatch>
            <FlowStep.Next>
              <FlowStep x:Name="__ReferenceID1">
                <sap:WorkflowViewStateService.ViewState>
                  <scg3:Dictionary x:TypeArguments="x:String, x:Object">
                    <av:Point x:Key="ShapeLocation">184.5,340.5</av:Point>
                    <av:Size x:Key="ShapeSize">211,59</av:Size>
                    <av:PointCollection x:Key="ConnectorLocation">310,210.5 310,309.5</av:PointCollection>
                  </scg3:Dictionary>
                </sap:WorkflowViewStateService.ViewState>
                <WriteLine sap:VirtualizedContainerService.HintSize="211,59" Text="Islemler tamamlandi">
                  <sap:WorkflowViewStateService.ViewState>
                    <scg3:Dictionary x:TypeArguments="x:String, x:Object">
                      <x:Boolean x:Key="IsExpanded">True</x:Boolean>
                    </scg3:Dictionary>
                  </sap:WorkflowViewStateService.ViewState>
                </WriteLine>
              </FlowStep>
            </FlowStep.Next>
          </FlowStep>
        </FlowStep.Next>
      </FlowStep>
    </Flowchart.StartNode>
    <x:Reference>__ReferenceID0</x:Reference>
    <x:Reference>__ReferenceID1</x:Reference>
    <x:Reference>__ReferenceID2</x:Reference>
  </Flowchart>
</Activity>

Workflow Application tarafindaki en önemli ayarlardan birisi de config dosyasinda yer almaktadir.

<?xml version="1.0"?>
<configuration>
    <startup>         
       <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.0"/>               
    </startup>
    <connectionStrings>
        <add name="ConStr" connectionString="User Id=bir kullanici adi;Password=bir sifre;Data Source=bir veri kaynagi" providerName="Oracle.DataAccess.Client"/>
    </connectionStrings>
    <system.serviceModel>
        <bindings>
            <wsHttpBinding>
                <binding name="WSHttpBinding_IAccountService" transactionFlow="true" />
            </wsHttpBinding>
        </bindings>
        <client>
            <endpoint address="http://localhost:35662/AccountService.svc"
                binding="wsHttpBinding" bindingConfiguration="WSHttpBinding_IAccountService"
                contract="IAccountService" name="WSHttpBinding_IAccountService">
                <identity>
                    <userPrincipalName value="bsenyurt@domain.bankanet.com.tr" />
                </identity>
            </endpoint>
        </client>
    </system.serviceModel>
</configuration>

Istemci tarafindaki Binding ayarlarinda da transactionFlow niteliginin mutlak suretle true olmasi gerekmektedir. Gelelim Main metodu içerisindeki kodlarimiza.

using System.Activities;
using System.Threading;

namespace HowToTransaction
{
    class Program
    {
        static void Main(string[] args)
        {
            var activity = new Workflow1();

            AutoResetEvent arEvent = new AutoResetEvent(false);
            WorkflowApplication wfApp = new WorkflowApplication(activity);
            wfApp.Extensions.Add(new CustomTracker());

            wfApp.Completed = (o) =>
            {
                arEvent.Set();
           };

            wfApp.Run();
           arEvent.WaitOne();
        }
    }
}

WorkflowApplication tipinden yararlanilarak Workflow1 örneginin baslatilmasi islemi gerçeklestirilmektedir. Tracking islemi için yazilmis olan CustomTracker sinifinin da, bir Extension olarak WorkflowApplication örnegine bildirilmesi gerekir.

Örnegi bu hali ile çalistirdigimda asagidaki sonuçlari elde ettigimi gördüm.

Workflow Foundation, Oracle, WCF ve TransactionScope

Workflow Foundation, Oracle, WCF ve TransactionScope

Workflow Foundation, Oracle, WCF ve TransactionScope

Workflow Foundation, Oracle, WCF ve TransactionScope

Ekran çiktisini okumak biraz zahmetli olabilir(Özellikle WCF servis çagrisinin yapildigi aktivite mesajlasma içerigini de bastigindan…) ama islemlerin basarili bir sekilde yapildigi görülmektedir ve dogal olarak veritabani tarafindaki insert islemleri de basarili olmustur. Özellikle activity tipleri için yapilan State bildirimlerine dikkatinizi çekerim.

Workflow Foundation, Oracle, WCF ve TransactionScope

Hatta Debug islemi yapildiginda servis tarafindaki operasyon içerisinde, istemci tarafindan gelen Transaction bilgileri de açik bir sekilde görülebilmektedir.

Workflow Foundation, Oracle, WCF ve TransactionScope

Dikkat edilecegi üzere DistributedIdentifier özelliginin GUID tipinden bir degeri mevcuttur. Bir baska deyisle DTC devreye girmis ve su andaki servis operasyonu içerisinde yapilacak islemler, Workflow Application tarafinda açilan TransactionScope’ a dahil edilmistir.

Eger InsertBranch Code Activity bileseni içerisindeki Exception firlatilan satir etkinlestirilirse,  Transaction islemlerinin Commit edilmedigi görülecektir. Bu kisim oldukça önemlidir. Çünkü Workflow1 akisinda önce akis içi bir Transaction islemi, sonrasinda servis tarafinda bir Transaction islemi ve son olarak da yine akis içerisinde bir Transaction islemi söz konusudur.

Son islemde olusan Exception nedeni ile bir adim önceki servis Transaction isleminin iptal edilmesi ve edildiginin görülmesi(tabi o ana kadarki tüm Insert’ lerin de iptal edildiginin görülmesi) son derece önemlidir. Bu, TransactionScope’ un basarili çalistiginin bir ispati olarak düsünülebilir.

Görüldügü üzere bir Workflow içerisinden baslatilan Transaction’ in, bir WCF servis operasyonuna aktarilabilmesi ve söz konusu operasyonun ilgili Transaction Scope’ a dahil hale gelerek Two Phase Commit metodolojisine uygun biçimde sisteme dahil edilmesi mümkündür. Bu, tipik anlamda bir Atomic Transaction senaryosudur. Sadece bir kaç küçük detaya ve ayarlamaya dikkat etmek gerekmektedir. Böylece geldik bir yazimizin daha sonuna. Tekrarda görüsünceye dek hepinize mutlu günler dilerim Winking smile

HowToTransaction.zip (457,18 kb)

[Örnek Visual Studio 2010, .Net Framework 4.0 tabanlidir]

Yazar Hakkında

Burak Selim Şenyurt

Burak Selim Şenyurt

buraksenyurt.com

Yıldız Teknik Üniversitesi Matematik Mühendisliği mezunu olan Şenyurt, 1999 yılında profesyonel olarak adım attığı yazılım dünyasında, 2003 yılından beri Microsoft .Net teknolojileri ile ilgilenmektedir. Yazılım hayatına Assist Line isimli Call Center firmasında Delphi programcısı olarak başlayan Şenyurt sonrasında, sırasıyla Bizitek(Junior Developer), Netron(Master Trainer), Citibank(Outsource Senior Software Developer), Innova(Application Development Consultant), ve TCM(Software Architect) firmalarında görev almıştır. Su anda ING Bank bünyesinde Kıdemli Yazılım Danışmanı olarak görev yapmaktadir. 2006, 2007 yıllarında C#, 2008,2009,2010 yıllarında ise Connected System Developer kategorisinde Microsoft MVP seçilen Şenyurt, evli ve 1 çocuk babasıdır. C# diline olan düşkünlüğü, oğluna S(h)arp adının verilmesinde önemli bir etken olmustur.

Sosyal Medya

ORANLAR

  • 4866izleme

Arkadaşlarınla Paylaş

  • Tweet

0 Yorum

Yorum Yaz / Soru Sor

Lütfen yorum yazmak veya soru sormak için üye girişi yapınız.

Son Yorumlar

  • Böyle bir sayfalama ağ trafiğini hafifleti...
  • Merhaba, ellerinize sağlık çok yardımcı ol...
  • Merhaba Bu uygulama örneğinden ASP.net ...
  • Hocam Link başka sayfaya yönlendiriyor.
  • merhaba benim merak ettiğim bir konu var y...

En Güncel Sorular

  • Bilgilendirme maili (C#.Net)
  • Power Pivot (Sharepoint 2010)
  • BigInteger, BigDecimal (Asp.Net ve Asp.Net MVC)
  • visual C# ile asp nette veritabanı islemleri (Asp.Net ve Asp.Net MVC)
  • Share Point ile Dosya Arşiv Yönetim Sistemi yapılabilir mi ? (Sharepoint 2010)

En Son Cevap Verilen Sorular

  • Bilgilendirme maili
  • BigInteger, BigDecimal
  • visual C# ile asp nette veritabanı islemleri
  • Share Point ile Dosya Arşiv Yönetim Sistemi yapılabilir mi ?
  • txt dosyasına veri yazma

Twitter

Takip et: @yazilim_dilleri

En Çok Okunanlar

Elif BAYRAKDAR

C# ile SQL Server Bağlantısı, Insert, Update ve Delete Sorguları

23.05.2013

  • 122279
  • 0
Hakan Keskin

C# ile Windows Service Projesi Oluşturma, Debug Etme ve Setup Hazırlama

17.12.2013

  • 68587
  • 0
batuhan avlayan

Php - Mail Gönderme (İletişim Formu)

02.09.2013

  • 50136
  • 0

Sponsorlar

KODLAB
Pluralsight
Exchange server is
Office 365
YAZILIM DİLLERİ
Yukarı Çık
  • Hakkımızda
  • Facebook
  • Twitter
  • RSS

© Yazılım Dillerinin Buluşma Noktası | Kaynak belirtildiği sürece makaleler kopyalanabilir.
YazilimDilleri.Net sitesinde yer alan kullanıcıların oluşturduğu tüm içeriklerin yayınlanması ile ilgili yasal yükümlülükler içeriği oluşturan kullanıcıya aittir, YazilimDilleri.Net hiçbir şekilde sorumlu değildir.

Kapat

Giriş Yap

Kullanıcı Adı

Şifre

Şifremi Unuttum

KULLANICI GİRİŞİ