//****************************************************************************
// (c) Copyright IBM Corp. 2007 All rights reserved.
//
// The following sample of source code ("Sample") is owned by International
// Business Machines Corporation or one of its subsidiaries ("IBM") and is
// copyrighted and licensed, not sold. You may use, copy, modify, and
// distribute the Sample in any form without payment to IBM, for the purpose
// of assisting you in the development of your applications.
//
// The Sample code is provided to you on an "AS IS" basis, without warranty
// of any kind. IBM HEREBY EXPRESSLY DISCLAIMS ALL WARRANTIES, EITHER EXPRESS
// OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. Some jurisdictions
// do not allow for the exclusion or limitation of implied warranties, so the
// above limitations or exclusions may not apply to you. IBM shall not be
// liable for any damages you suffer as a result of using, copying, modifying
// or distributing the Sample, even if IBM has been advised of the
// possibility of such damages.
//
//**************************************************************************
//
// SOURCE FILE NAME: LCTrans.cs
//
// SAMPLE: Demonstrates loosely coupled transactions
//         with the DB2 .NET Data Provider
//
// SQL Statement USED:
//         SELECT
//
// DB2 .NET Data Provider Classes USED:
//         DB2Connection
//         DB2Command
//         
//                           
//****************************************************************************
//
// Building and Running the sample program 
//
// Using the bldapp.bat batch file: 
//
// 1. Create a new key pair and store it in SubCOM.snk by entering the 
//    following at the command prompt:
//
//     sn -k SubCOM.snk
//
// 2. Compile the SubCOM.cs file with bldapp.bat by entering the following 
//    at the command prompt:
//
//      bldapp SubCOM
// 
// 3. Create a new key pair and store it in RootCOM.snk by entering the 
//    following at the command prompt:
//
//      sn -k RootCOM.snk
//
// 4. Compile the RootCOM.cs file with bldapp.bat by entering the following 
//    at the command prompt:
//
//      bldapp RootCOM
// 
// 5. Compile the LCTrans.cs file with bldapp.bat by entering the following 
//    at the command prompt:
//
//      bldapp LCTrans
//  
// 6. Register the COM+ objects with regCOM.bat by entering the following   
//    at the command prompt:
//
//      regCOM
//
// 7. Run the LCTrans program by entering the program name at the command 
//    prompt followed by a user id and password for the SAMPLE database:
//
//      LCTrans <userid> <password>
//
// Using the makefile:
//
// 1  Build the assembly SubCOM.dll and RootCOM.dll and compile LCTrans.cs
//    with the makefile by entering the following at the command prompt:
//
//      nmake LCTrans
//
// 2. Register the COM+ objects with regCOM.bat by entering the following   
//    at the command prompt:
//
//      regCOM
//
// 3. Run the LCTrans program by entering the program name at the command 
//    prompt followed by a user id and password for the SAMPLE database:
//
//      LCTrans <userid> <password>
//
//****************************************************************************
//
// For more information on the sample programs, see the README file.
//
// For information on developing applications, see the Application
// Development Guide.
//
// For information on using SQL statements, see the SQL Reference.
//
// For the latest information on programming, compiling, and running DB2
// applications, visit the DB2 Information Center at
//     http://publib.boulder.ibm.com/infocenter/db2luw/v9r7/index.jsp
//
//****************************************************************************
using  System.EnterpriseServices;
using System;
using System.IO;
using System.Data;
using IBM.Data.DB2;
using Microsoft.VisualBasic;
using System.Reflection;
using System.Runtime.InteropServices;
using RootCOM;

class  LCTrans
{
	public static String strUID = "";
	public static String strPWD = "";
	public static String strEmpJob;
	public static void Main(String[] CmdArgs)
	{
		Decimal decIncrease = 5000;
		String strNewJob = "Mgr";
		String strOldJob;
		UpdateEmpInfoCOM comRootCOM;

		Console.WriteLine();
		Console.WriteLine("  THIS SAMPLE DEMONSTRATES LOOSELY COUPLED TRANSACTIONS IN DB2\n" +
						  "  USING MICROSOFT .NET");
		Console.WriteLine();

		// Check if the user id and password have been entered
		switch (CmdArgs.Length)
		{
			case 0:
				strUID = null;
				strPWD = null;
				break;
			case 2:
				// Obtain the user id and password
				strUID = Convert.ToString(CmdArgs[0]);
				strPWD = Convert.ToString(CmdArgs[1]);
				break;
			default:
				Console.WriteLine("  Invocation:");
				Console.WriteLine();
				Console.WriteLine("  LCTrans");
				Console.WriteLine("  or");
				Console.WriteLine("  LCTrans <USERID> <PASSWORD>");
				return;
		}

		Console.WriteLine("\n  DEMONSTRATE LOOSELY COUPLED TRANSACTION IN WHICH ONE" +
						  " FAILS CAUSING\n  BOTH TO ROLLBACK\n");

		// Display the salary and job title of employee id = 320 before the transaction
		Console.WriteLine("\n  EMPLOYEE INFO BEFORE THE TRANSACTION\n");

		PrintEmpInfo(320, ref strEmpJob);

		// Create a RootCOM instance. The root component invokes a sub component to demonstrate loosely coupled transactions
		comRootCOM = new UpdateEmpInfoCOM();

		// Demonstrate a case where one operation of the transaction fails causing both
		// operaions to be rolled back. Employee id = 320 has been an employee
		// for less 5 years and so, should not have a salary > 20000. 
		// The sub component aborts the transaction because it finds the salary of empid 320 will be greater than 20000

		comRootCOM.UpdateEmpInfo(320, decIncrease, strNewJob, strUID, strPWD);

		// Display the salary and job title of employee id = 320 after the transaction
		// Nothing should be changed because of the rollback in the sub component.
		Console.WriteLine("\n  EMPLOYEE INFO AFTER THE TRANSACTION\n");
		PrintEmpInfo(320, ref strEmpJob);

		// Demonstrate a case where all operations are successful causing
		// them to be committed.
		Console.WriteLine( "\n\n  DEMONSTRATE LOOSELY COUPLED TRANSACTIONS THAT ARE COMPLETED" +
						   "\n  SUCCESSFULLY AND ARE THEREFORE COMMITTED\n" );

		// Display the salary and job title of employee id = 320 before the transaction
		Console.WriteLine("\n  EMPLOYEE INFO BEFORE THE TRANSACTION\n");

		PrintEmpInfo(20, ref strEmpJob);

		//Save the old job so we can do the unchanges
		strOldJob = strEmpJob;

		comRootCOM = new UpdateEmpInfoCOM();
		comRootCOM.UpdateEmpInfo(20, decIncrease, strNewJob, strUID, strPWD);

		// Display the salary and job title of employee id = 20 after the transaction
		// They should be changed.

		Console.WriteLine("\n  EMPLOYEE INFO AFTER THE TRANSACTION\n");
		PrintEmpInfo(20, ref strEmpJob);

		// Undo the changes made to the SAMPLE database
		Console.WriteLine("\n  UNDO THE CHANGES MADE TO THE 'SAMPLE' DATABASE");

		comRootCOM = new UpdateEmpInfoCOM();
		comRootCOM.UpdateEmpInfo(20, -decIncrease, strOldJob, strUID, strPWD);

		Console.WriteLine("\n  EMPLOYEE INFO AFTER THE UNDO\n");

		PrintEmpInfo(20, ref strEmpJob);

		return;
	
	}

	// This method displays the job title and salary of the employee
	// with id = empID
	public static void PrintEmpInfo(int IntEmpID, ref String StrJob)
	{
		Decimal  decEmpSalary;
		DB2Connection objConnection;
		DB2Command objCommand = new DB2Command();
		DB2DataReader objReader;

		if (strUID == "")
		{
			objConnection = new DB2Connection("database=sample;enlist=false");
		}
		else
		{
			objConnection = new DB2Connection("database=sample;UID=" + 
                                                          strUID + ";PWD=" + strPWD + 
                                                          ";enlist=false");
		}
	
		// Connect to the SAMPLE database
		try
		{
			objConnection.Open();
		}
		catch (Exception e)
		{
			Console.WriteLine( "LCTrans: Failed to open connection to the SAMPLE database!");
			Console.WriteLine(e.ToString());
			return;
		}

		objCommand.CommandText = "select SALARY, JOB from STAFF where ID = " + IntEmpID;
		objCommand.Connection = objConnection;

		// Execute the query
		try
		{
			objReader = objCommand.ExecuteReader();
			if (objReader.Read()) 
			{
				decEmpSalary = objReader.GetDecimal(0);
				StrJob = objReader.GetString(1);

				// Display the details of the employee
				Console.WriteLine( "  Salary of employee id = " + IntEmpID + " in table STAFF: " + decEmpSalary);
				Console.WriteLine("  Job of employee id = " + IntEmpID + " in table STAFF: " + StrJob);
			}
			
			objReader.Close();
		}
		catch (Exception e)
		{
			Console.WriteLine("LCTrans: Failed to fetch from table STAFF!");
			Console.WriteLine(e.ToString());
		}

		objConnection.Close();
	}
}