Paolo Pialorsi - Bridge The Gap!

Living in a Service Oriented World

June 2005 - Posts

Distributed Transactions with Indigo and WS-AT

This evening I played with Indigo and WS-AT, to see if it works, in order to use it in a project of a customer of mine.

First of all the good news: it works :-) as it did in PDC03 bits! Great job guys!
Second news: it's not so easy to manage all the stuff, but at least it works fine.

I developed two different services, working on a couple of SQL Server 2005 database.
One service is exposed using a net.tcp (netProfileTcpBinding) binding. The other is exposed using http (wsProfileBinding), self-hosted.

Both are used by a third party client, that covers the transactional work with a TransactionScope.

Here is a sample of one of the two transactional services:

namespace ServiceOne
{
 [ServiceContract(
  FormatMode=ContractFormatMode.XmlFormatter,
  Namespace="
http://schemas.devleap.com/Services/OrderService1",
  Style=ServiceOperationStyle.DocumentBare,
  Use=ServiceOperationBindingUse.Literal)]
 [BindingRequirements(
  TransactionFlowRequirements = RequirementsMode.Require)]

 public interface ITxServiceOne
 {
  [OperationContract(
   Action="urn:saveOrder1")]
  Int32 SaveOrder(OrdersLibrary.Order order);
 }
 
 [ServiceBehavior(
  AllowConcurrentTransactions=true,
  TransactionIsolationLevel=IsolationLevel.ReadCommitted)]
 public class TxServiceOne: ITxServiceOne
 {
  [OperationBehaviorAttribute(
   AutoEnlistTransaction = true,
   AutoCompleteTransaction = true)]
  public int SaveOrder(OrdersLibrary.Order order)
  {
   OrdersLibrary.OrderBiz ob = new OrdersLibrary.OrderBiz();
   return (ob.SaveOrder(order));
  }
 }
}

Take care of BindingRequirements and OperationBehavior attributes, respectively on the service contract and on the operation implementation.

Here is the service side configuration file:

<?xml version="1.0" encoding="utf-8" ?>
<configuration xmlns="
http://schemas.microsoft.com/.NetConfiguration/v2.0">
 <appSettings>
  <add key="SqlConnectionString" value="..."/>
 </appSettings>
 <system.serviceModel>
  <services>
   <service
    serviceType="ServiceOne.TxServiceOne, ServiceOne"
    behaviorConfiguration="txServiceBehavior">
    <endpoint
     contractType="ServiceOne.ITxServiceOne, ServiceOne"
     address="
http://localhost:35000/TxServiceOne.svc"
     bindingConfiguration="txBinding"
     bindingSectionName="wsProfileBinding" />
   </service>
  </services>
  <bindings>
   <wsProfileBinding>
    <binding configurationName="txBinding" flowTransactions="Required" />
   </wsProfileBinding>
  </bindings>
  <behaviors>
   <behavior
    configurationName="txServiceBehavior"
    returnUnknownExceptionsAsFaults="true" >
   </behavior>
  </behaviors>
 </system.serviceModel>
</configuration>


Pay attention to the behaviors section, where I declare to manage any exception as a Fault.
Take a look also at the custom binding configuration, defined in order to require transactions.
The other service is very similar to the first one.

Lastly here is the main part of client code:

schemas.devleap.com.EntitiesOrder.Order order = new schemas.devleap.com.EntitiesOrder.Order();
order.id = 10;
order.description = "Order 10";

TransactionOptions options = new TransactionOptions();
options.IsolationLevel = IsolationLevel.ReadCommitted;
options.Timeout = TimeSpan.FromSeconds(30);

using(TransactionScope scope = new TransactionScope(TransactionScopeOption.Required, options))
{
 TxServiceOneProxy svcOne = null;
 TxServiceTwoProxy svcTwo = null;
 
 try
 {
  // External transactional activity
  svcOne = new TxServiceOneProxy();
  Console.WriteLine("Service One: {0}", svcOne.SaveOrder(order));

  try
  {
   // Internal transactional activity
   svcTwo = new TxServiceTwoProxy();
   Console.WriteLine("Service Two: {0}", svcTwo.SaveOrder(order));

   // Transaction commit, in case of success
   scope.Complete();
   
  }
  finally
  {
   // Internal channel closing
   svcTwo.Close();
  }
 }
 finally
 {
  // External channel closing
  svcOne.Close();
 }
}

Here you can find all the code of the demo solution I developed to test WS-AT support in Indigo.

In order to make it work, don't forget to download this fix (published on 21/06/2005):

http://www.microsoft.com/downloads/details.aspx?familyid=32187993-4736-4a06-97c7-1282b67e3137&displaylang=en

I hope you'll enjoy your Indigo transactional experience :-) !

Posted: Jun 23 2005, 02:13 AM by paolopia | with 5 comment(s)
Filed under: ,
Working with Dynamic C# 2.0 Generics

Yesterday I was involved in working with dynamic generic types for a project I'm working on. At least I achieved this solution to dinamically create a Generic Type for instance reading a .config file:

using System;
using System.Collections.Generic;
using System.Text;

namespace DynamicGeneric
{
 class Program
 {
  static void Main(string[] args)
  {
   // "Standard" generic instantiation
   GenericClass<PaoloEntity> paoloGenericClass = new GenericClass<PaoloEntity>();
   Console.WriteLine(paoloGenericClass.GetEntity());

   // Create a parametric generic type instance
   Type paoloEntityType = Type.GetType("DynamicGeneric.PaoloEntity, DynamicGeneric");
   Type paoloGenericClassType = typeof(GenericClass<>).MakeGenericType(paoloEntityType);
   Object paoloGenericClassDynamic = Activator.CreateInstance(paoloGenericClassType);
   Console.WriteLine(paoloGenericClassDynamic.ToString());
   GenericClass<PaoloEntity> paoloGenericClassDynamic2 = (GenericClass<PaoloEntity>)paoloGenericClassDynamic;
   Console.WriteLine(paoloGenericClassDynamic2.GetEntity());
  }
 }

 public class BaseEntity
 {
  private String _name;

  public String Name
  {
   get { return(this._name); }
   set { this._name = value; }
  }
 }

 public class PaoloEntity: BaseEntity
 {
  public PaoloEntity()
  {
   this.Name = "Paolo";
  }

  public override string ToString()
  {
   return (String.Format("Entity: {0}", this.Name));
  }
 }

 public class GenericClass<TEntity>
  where TEntity : BaseEntity, new()
 {
  public TEntity GetEntity()
  {
   return (new TEntity());
  }
 }
}

The only last problem I'm facing on is the ability not only to create an instance but also to declare a Generic Type dinamically. I mean something like:

GenericClass<typeof(paoloGenericClassType)> paoloGenericClassDynamic = ....

Of course the above line does not compile, because the compiler needs to know the generic parameter type provided to the Generic Type called "GenericClass" (I guess). On the other side I don't want to declare my Generic Type instance as an Object ... I'd loose all the benefits of generics ..... Any idea?

Update: of course I know that I can use a base class or interface for my GenericClass, in order to have a common signature for my GetEntity method instead of having just an Object. The problem that I've in my real application (not in the snippet published here) is that my GenericClass (that in reality are many classes) have a base interface that is based on generics too... probably I'm wondering too much from my life! :-)

Posted: Jun 11 2005, 10:39 AM by paolopia | with 9 comment(s)
Filed under:
More Posts