locked
does WCF data service support transactions ? RRS feed

  • Question

  • Title says the question.

     

    by the way i am using silverlight with ado.net data services .

    Thursday, April 1, 2010 3:53 AM

Answers

  • It is supported on .NET Framework 3.5 if you install the latest available data services update for .NET Framework 3.5. Take a look at this blog post:

    http://blogs.msdn.com/astoriateam/archive/2010/01/27/data-services-update-for-net-3-5-sp1-available-for-download.aspx

    It contains links to downloads as well as the list of features included in the update.

    Thanks

    Pawel

    Monday, May 3, 2010 7:47 PM
  • I created a short example that is using TransactionScope. I was using Entity Framework as my data provider and it appeared to work.

    public class WcfDataService1 : DataService<WebApplication2.AdHocContainer7StorageEntities>, IDisposable
        {
            private TransactionScope transaction;
            private bool disposed;
            private bool error;
    
            public WcfDataService1()
            {
                this.ProcessingPipeline.ProcessingChangeset += new EventHandler<EventArgs>(ProcessingPipeline_ProcessingChangeset);
                this.ProcessingPipeline.ProcessedChangeset += new EventHandler<EventArgs>(ProcessingPipeline_ProcessedChangeset);
            }
    
            ~WcfDataService1()
            {
                Dispose(false);
            }
    
            public static void InitializeService(DataServiceConfiguration config)
            {
                config.SetEntitySetAccessRule("*", EntitySetRights.All);
                config.DataServiceBehavior.MaxProtocolVersion = DataServiceProtocolVersion.V2;
                config.UseVerboseErrors = true;
            }
    
            private void ProcessingPipeline_ProcessingChangeset(object sender, EventArgs args) 
            {
                transaction = new TransactionScope(TransactionScopeOption.Required, new TimeSpan(0, 0, 30));
            }
    
            private void ProcessingPipeline_ProcessedChangeset(object sender, EventArgs args) 
            {
                if (!error)
                {
                    transaction.Complete();
                }
                this.Dispose(); // will rollback the transaction if it has not been commited
            }
    
            protected override void  HandleException(HandleExceptionArgs args)
            {
                error = true;
     	        base.HandleException(args);
            }
    
            public void Dispose()
            {
                Dispose(true);
                GC.SuppressFinalize(this);
            }
    
            protected virtual void Dispose(bool disposing)
            {
                if(!disposed)
                {
                    if(disposing)
                    {
                        if (transaction != null)
                        {
                            transaction.Dispose();
                        }
                    }
    
                    disposed = true;
                }
            }
        }

    Hope this helps.

    Pawel

    Monday, April 12, 2010 7:20 PM

All replies

  • Hi,

    Please note that WCF Data Services currently does not direcly support transactions. That feature has to be implemented on the server. You should be able to use the processing pipeline events to do this though (http://msdn.microsoft.com/en-us/library/ee474212.aspx).

    Thanks,
    Vitek Karas [MSFT]
    Thursday, April 1, 2010 8:19 AM
    Moderator
  •  

     

    i am using silverlight(v-4) with wcf data services(.net 4.0) , please provide more guidance . i mean any steps ? because i dont find much information on WCF data services or ado.net data service transactions

    Thursday, April 1, 2010 1:51 PM
  • There is no transactions on the client. On the server you can use processing pipeline to handle transactions. Note that this only makes sense for batch requests as Create/Update/Delete operations involves only one entity at a time. For batches you can use the following events to handle transactions:

    DataServiceProcessingPipeline.ProcessingChangeset - this is where we start processing the whole batch - you Begin Tran here.

    DataServiceProcessingPipeline.ProcessedChangeset - this is where we finish processing the whole batch - you Commit Tran or if exception occured Rollback Tran here

    DataService.HandleException - if an exception happens this method will be called. Here you can set a flag saying that the exception occured so that you know if you want to Commit or Rollback your transaction.

    Hope this helps.

    Pawel

    Friday, April 9, 2010 6:52 PM
  • hi again , first of all i would say ,  May God Bless you for the help you offered .

    secondly i would like to have some more of you opinions .

    you said , "Note that this only makes sense for batch requests" this means when calling DataServiceContext's BeginSaveChanges method from my Silverlight App , i should set SaveChangesOptions. Batch right ?

    now , to handle the events that you suggested , i made a constructor to set the handlers of the event , is this right ?


            public V3CDataBaseService()
            {
                this.ProcessingPipeline.ProcessingChangeset += new EventHandler<EventArgs>(ProcessingPipeline_ProcessingChangeset);
                this.ProcessingPipeline.ProcessedChangeset += new EventHandler<EventArgs>(ProcessingPipeline_ProcessedChangeset);
            }


    now how am i supposed to begin and end the transaction? any sample code ?

     

    P.S , i didn't find any document or event any ebook ,  please suggest me something in this regard.

    Saturday, April 10, 2010 10:17 AM
  • Transactions only make sense if you want to process more than one entity at the same time. In WCF Data Services creating (POST), updating (PUT/MERGE) and deleting (DELETE) operations work with one entity at the same time (i.e. you cannot create, update or delete more than one entity with a single request). So in non-batch request the operation either succeeds or fails and there is no need for transaction. Batch requests allow you to send requests that contain multiple POST/PUT/MERGE/DELETE operations inside. The transaction would guard that if one of operations in the batch failed none of the operation from the batch would go through. How to handle the transaction depends on the storage you are using. In the SqlServer database you have BEGIN TRAN, COMMIT TRAN and ROLLBACK TRAN commands to with transactions. You call BEGIN TRAN to start the transaction. Then you modify the data in the database and finally you either COMMIT TRAN if everything went good or ROLLBACK if something went wrong. When you call ROLLBACK TRAN or queries you executed after calling BEGIN TRAN will have no effect on your database.

    Thanks

    Pawel

    Monday, April 12, 2010 5:20 PM
  • I created a short example that is using TransactionScope. I was using Entity Framework as my data provider and it appeared to work.

    public class WcfDataService1 : DataService<WebApplication2.AdHocContainer7StorageEntities>, IDisposable
        {
            private TransactionScope transaction;
            private bool disposed;
            private bool error;
    
            public WcfDataService1()
            {
                this.ProcessingPipeline.ProcessingChangeset += new EventHandler<EventArgs>(ProcessingPipeline_ProcessingChangeset);
                this.ProcessingPipeline.ProcessedChangeset += new EventHandler<EventArgs>(ProcessingPipeline_ProcessedChangeset);
            }
    
            ~WcfDataService1()
            {
                Dispose(false);
            }
    
            public static void InitializeService(DataServiceConfiguration config)
            {
                config.SetEntitySetAccessRule("*", EntitySetRights.All);
                config.DataServiceBehavior.MaxProtocolVersion = DataServiceProtocolVersion.V2;
                config.UseVerboseErrors = true;
            }
    
            private void ProcessingPipeline_ProcessingChangeset(object sender, EventArgs args) 
            {
                transaction = new TransactionScope(TransactionScopeOption.Required, new TimeSpan(0, 0, 30));
            }
    
            private void ProcessingPipeline_ProcessedChangeset(object sender, EventArgs args) 
            {
                if (!error)
                {
                    transaction.Complete();
                }
                this.Dispose(); // will rollback the transaction if it has not been commited
            }
    
            protected override void  HandleException(HandleExceptionArgs args)
            {
                error = true;
     	        base.HandleException(args);
            }
    
            public void Dispose()
            {
                Dispose(true);
                GC.SuppressFinalize(this);
            }
    
            protected virtual void Dispose(bool disposing)
            {
                if(!disposed)
                {
                    if(disposing)
                    {
                        if (transaction != null)
                        {
                            transaction.Dispose();
                        }
                    }
    
                    disposed = true;
                }
            }
        }

    Hope this helps.

    Pawel

    Monday, April 12, 2010 7:20 PM
  • very thankful to you for the help you gave .

    i will implement this functionality in a week , so once i complete it than i will close this ticket .i hope you dont mind that .

    thanks

    Jamal.

    Tuesday, April 13, 2010 7:04 AM
  • It took me some time to find out that:

    DataService<T>.ProcessingPipeline is only supported in .NET Framework 4

    (see http://msdn.microsoft.com/en-us/library/ee474212.aspx )

    So the above information does not apply to .NET Framework 3.5

    Monday, May 3, 2010 7:05 PM
  • It is supported on .NET Framework 3.5 if you install the latest available data services update for .NET Framework 3.5. Take a look at this blog post:

    http://blogs.msdn.com/astoriateam/archive/2010/01/27/data-services-update-for-net-3-5-sp1-available-for-download.aspx

    It contains links to downloads as well as the list of features included in the update.

    Thanks

    Pawel

    Monday, May 3, 2010 7:47 PM
  • Just so I understand this right -

    All you have to do is implement the two events 

    ProcessingPipeline.ProcessingChangeset and ProcessingPipeline.ProcessedChangeset

    on your WCF data service which is exposing your EF and that is it? And no changes in client as long as the two entities are saved in one operation. So if I have, say, add an item and then update a log about it like this and call saveChanges on the context it will be in a trasaction?

    Context ct = = new context()

    item = from c  in ct.items where c.id = 1 select c;

    c.name = "new name"

    logitem = from L in ct.logitems where L.id = 1 select L;

    L.update_time = now

    ct.savechanges();

     

    And the two entities items and log will be in a transatction?

    Some real code will be useful.

    Thanks.

     

    Tuesday, February 1, 2011 12:08 AM
  • Tuesday, February 1, 2011 3:11 PM
  • Hi Pawel,  Thank you for that, with a bit more research I understood how clever that piece of code was. I eventually worked out that once that was included in my WCF data service, I was then able to do normal EF updating. However with a transaction scope I normally do a number of SaveChanges() along the way when I finally end the scope. In the above case I changed the client code to not reference a transaction scope at all as this was happening in the WCF data service, then in my client code did all the EF updates and then do the save changes as follows....

    . oWCFContext.UpdateObject (blah)

    . oWCFContext.AddtoTable(rec1)

    . oWCFContext.AddtoAnotherTable(rec2)

    . oWCFContext.SaveChanges(SaveChangesOption.Batch)

    and it worked. I even tested it by throwing an exception in the middle of it and it correctly rolledback for me.

    I would like to see a cleaner approach supported at the client, but that will keep us moving for now :)

    Thanks again.


    Friday, November 14, 2014 5:21 AM