3

I'm having an issue where I'm preaty not sure how to resolve this and I want to know what is the best approach I should consider in order to achieve this task.

We are developping an application VB.net 2.0 and SQL 2005. Users are allowed to cancel a reception based on a purchase which may contains many received goods. But, during the process of cancellation, some questions are asked to users such as "Do you want to cancel Good #1". If yes, delete. Then, "Do you want to cancel Good #2", no, do not delete and one another question (if received item is issued, a process must be made manualy by the user). And, at the end, if all goods were successfully cancelled, we have to cancel the reception itself. But sometime, if an error occurs or some conditions occurs once asked to user in this process, we want to cancel any actions made from the beginning and make it back to his original state. So I thought about Transaction.

  1. I know there is Transaction for SQL which can be used and I know good enough how to use it, but I can't realy use this as user must perform actions which possibly cancel this transaction.

  2. I also remembered TransactionScope from .NET 2.X and over which can achieve something similar and I also know as well how to use it. The problem comes with TransactionScope and MSDTC. When using this, we still getting an error which said :

Network access for Distributed Transaction Manager (MSDTC) has been disabled. Please enable DTC for network access in the security configuration for MSDTC using the Component Services Administrative tool.

I've tried what is describe here in another stack post and it works great... until user restard their computer. EVERY time users restart their computer, they must put value back. Plus, per default, no computer have this value set to On. At least on 10 computers bases, none were activated. There is something like 300 computers on which this program is installed so it's surely not the good things to consider neither.

So anyone have an idea of how I can acheive this? Is there anything else doing transaction via code which I can use?

NOTE1 : I know some would say, first ask conditions to user and maintain values in memory. Once done, if everything went well, go with delete. But what if an error occurs when deleting let's say, goods #4? And how can I give to a store procedure a dynamic list of goods to be deleted?

NOTE2 : Sorry for my english, I usualy talk french.

NOTE3 : Any exemple in C# can be provide also as I know both VB and C#.

Community
  • 1
  • 1
Simon Dugré
  • 17,980
  • 11
  • 57
  • 73
  • If you do what NOTE1 says, embedd deletes into transaction and rollback if an error occures. See [SET XACT_ABORT ON](http://msdn.microsoft.com/en-us/library/ms188792%28v=sql.90%29.aspx) for details on automatic rollback within batch. – Nikola Markovinović May 04 '12 at 17:12
  • Yup, but I still have the problem that I may cancel Good #1, 3, 4, 5, 8 from a reception #A. How can I pass a dynamic array to a stored procedure? Is there a way? – Simon Dugré May 04 '12 at 17:15
  • There is XML datatype in sql server so one might pass all sorts of things as XML parameter. But I was thinking that you could build sql statement yourself in response to users actions and `ExecuteNonQuery` this batch. – Nikola Markovinović May 04 '12 at 17:19
  • Current actions perform 2 updates on 2 seperated tables for each goods and finaly execute 2 stored procedures once, or if, all goods were canceled. It's hard to regroup this in a same `ExecuteNonQuery` procedure... – Simon Dugré May 04 '12 at 17:22

1 Answers1

1

Assuming you already have similar stored procedure to manage cancelation:

create proc CancelGood (@goodID int)
as
   SET NOCOUNT ON
   SET XACT_ABORT ON

   begin transaction

   update table1 set canceled = 1
    where GoodID = @GoodID

   update table2 set on_stock = on_stock + 1
    where GoodID = @GoodID

   commit transaction

VB code adds a string to some canceledGoods list if user selects 'Oui'. I'm not familiar with VB.Net; in c# it would look like:

canceledGoods.Add (string.Format("exec dbo.CancelGood {0}", goodID));

Than, if there is at least one string in canceledGoods, build and execute batch:

batch = "BEGIN TRANSACTION" +
        " BEGIN TRY " +
        string.Join (Environment.NewLine, canceledGoods.ToArray()) + 
        " END TRY" +
        " BEGIN CATCH " +
        " -- CODE TO CALL IF THERE WAS AN ERROR" +
        "    ROLLBACK TRANSACTION" +
        "    RETURN" +
        " END CATCH" +
        " -- CODE TO CALL AFTER SUCCESSFULL CANCELATION OF ALL GOODS" +
        " COMMIT TRANSACTION"

conn.ExecuteNonQuery (batch);
Nikola Markovinović
  • 18,963
  • 5
  • 46
  • 51
  • That's ok for C#, I used to do only C# before this project so I'm preaty familar with both. I'll give a try to what you wrote and come back later. But, there's a lot of jobs for sure on my side as I've explain only a small part of my problem. I've got to try thinking back to how to do this using these methods. Probably more easly for me to use second part as I'm more familiar with .NET code comparativly to SQL. – Simon Dugré May 04 '12 at 18:06