C# .NET Interface
This chapter describes an example program that uses functions used by a C# .NET interface.
A C# .NET interface that spports Unicode is similar to a Visual Basic .NET interface. For information about functions used by a C# .NET interface, refer to Visual Basic .net Interface (Unicode). |
1. Overview
A C# .NET interface has interface modules that define functions' prototypes to call a client library.
If the following interface modules are installed, functions provided by a Tmax client library can be called and used. For information about the functions, refer to an example program for managing employees in Client Program.
Module | Description |
---|---|
Atmi.cs |
Module that defines ATMI functions' prototypes. |
Fdl.cs |
Module that defines field key functions' prototypes. |
Tx.cs |
Module that defines transaction-related functions' prototypes. |
WinApi.cs |
Module that defines prototypes of functions provided by Windows. |
TmaxApi.cs |
Module that defines prototypes of functions for RQ, unrequested messages, etc. |
For information about prototypes and descriptions of ATMI and field key functions, refer to Tmax Reference Guide and Tmax Application Development Guide. For information about how to use a C# interface, refer to an example program in the next section. |
2. Example Program
The following describes an example program that queries, modifies, deletes, and adds names, positions, managers in charge, joining dates, salaries, contracted periods, and departments with a key of an employee number. Filed key buffers are used in the program.
2.1. Program Organization
Each program consists of the following files.
-
Common program
File Description demo.f
Defines field key buffers.
tmconfig.m
Tmax configuration file.
-
Client program
File Description 4GL_Sample.sln
Client program that consists of Form1.cs and a Tmax library.
-
Server program
File Description emp_c.pc
Server program that provides services (Oracle source).
emp_c.mk
Makefile.
2.2. Program Description
The following describes each program.
-
Client program
Item Description Tmax library connection
Atmi.cs, Fdl.cs, Tx.cs, WinApi.cs, and TmaxApi.cs are added.
Tmax connection
A connection is established whenever a service operates and ended after the service completes.
Buffer
'fdl' files need to be created by compiling FIELD KEY buffers and field key files with the fdlc utility.
Communication
Synchronous communication is made by using pb_tpcall().
Transaction
Transactions for queries, modifications, deletions, and additions are handled.
-
Server program
Item Description Service
FDLSELECT, FDLUPDATE, FDLDELETE, and FDLINSERT are written.
Database
Oracle database is used. Database information (XA method) is specified in SVRGROUP of a system configuration file.
2.3. Common Program
DataBase EMP Table
The following is an example EMP table created in a database.
EMPNO NUMBER NOT NULL P1 ENAME VARCHAR(16) JOB VARCHAR(16) MGR NUMBER HIREDATE DATE SAL NUMBER(7,2) COMM NUMBER(7,2) DEPTNO NUMBER
Field Key Buffer Definition
The following is an example file that defines a field key buffer.
<demo.f>
#For tmax demo employee program EMPNO 7500 long - - ENAME 7501 string - - JOB 7502 string - - MGR 7503 long - - DATE 7504 string - - SAL 7505 float - - COMM 7506 float - - DEPTNO 7507 long - - E_TYPE 9009 long - - E_CODE 9010 long - - E_MSG 9011 string - - E_TMP 9012 long - -
Tmax Configuration
The following is an example Tmax configuration file.
<tmconfig.m>
*DOMAIN dom1 SHMKEY = 70000, MAXUSER = 200, MINCLH = 1, MAXCLH = 5, TPORTNO = 8888, BLOCKTIME = 200, TXTIME = 200 *NODE tmax1 TMAXDIR = "/home/tmax", APPDIR = "/home/tmax/appbin", PATHDIR = "/home/tmax/path", TLOGDIR = "/home/tmax/log/tlog", SLOGDIR = "/home/tmax/log/slog" ULOGDIR = "/home/tmax/log/ulog" *SVRGROUP svg1 NODENAME = tmax1, DBNAME = ORACLE, OPENINFO = "ORACLE_XA+Acc=P/scott/tiger+SesTm=60", TMSNAME = svg1_tms *SERVER emp_c SVGNAME = svg1, MIN = 1 *SERVICE FDLSELECT SVRNAME = emp_c FDLUPDATE SVRNAME = emp_c FDLDELETE SVRNAME = emp_c FDLINSERT SVRNAME = emp_c
2.4. Client Program
Employee Management Program
The following is an initial screen that consists of 1 data window, 8 singleline editor, and 5 buttons.
The following describes each button.
-
Search
Click the [Search] button after entering 'Employee Number' to display data with the entered employee number ±50 in the data window.
The following shows an example result.
-
Modification
Click the [Modify] button after entering 'Employee Number' and new data to replace existing data with the new data.
-
Deletion
Click the [Delete] button after entering 'Employee Number' to delete the corresponding data.
-
Addition
Click the [Add] button after entering all data for an employee to add the employee.
-
Exit
Click the [Exit] button to exit the program.
This section describes 2 example program design sources: Unicode programming and general programming.
The following is an example of general programming source for managing employees.
<Form1.cs>
using System; using System.Drawing; using System.Collections; using System.ComponentModel; using System.Windows.Forms; using System.Data; using AtmiNS; using WinApiNS; using FdlNS; using TxNS; using TmaxApiNS; namespace _4GL_Sample { public class EmployeeMgr : System.Windows.Forms.Form { private Atmi atmi = new Atmi(); private WinApi winApi = new WinApi(); private Fdl fdl = new Fdl(); private Tx tx = new Tx(); private TmaxApi tmaxApi = new TmaxApi(); bool bTxRun, bConnect; int nSndBuf, nRcvBuf; public string[] EmpFKey = {"EMPNO","ENAME","JOB","MGR","DATE","SAL","COMM","DEPTNO"}; public string[] ErrFKey = {"E_TYPE","E_CODE","E_MSG","E_TMP"}; public string[] ColumnName = {"EmpNo","Name","Position","Mgr","JoinDate","Salary","COMM","Dept"}; public const int FIELD_NUM = 8; public const int ErrFLD_NUM = 4; public enum InputCheck { Pri_Key, All }; private System.Windows.Forms.Label label1; private System.Windows.Forms.Label label2; private System.Windows.Forms.Label label3; private System.Windows.Forms.Label label4; private System.Windows.Forms.Label label5; private System.Windows.Forms.Label label6; private System.Windows.Forms.Label label7; private System.Windows.Forms.Label label8; private System.Windows.Forms.GroupBox groupBox1; private System.Windows.Forms.TextBox EditEmpNo; private System.Windows.Forms.TextBox EditName; private System.Windows.Forms.TextBox EditJob; private System.Windows.Forms.TextBox EditMgr; private System.Windows.Forms.TextBox EditDate; private System.Windows.Forms.TextBox EditSal; private System.Windows.Forms.TextBox EditComm; private System.Windows.Forms.TextBox EditDept; private System.Windows.Forms.Label LabelErr; private System.Windows.Forms.Button BtnSel; private System.Windows.Forms.Button BtnUpt; private System.Windows.Forms.Button BtnDel; private System.Windows.Forms.Button BtnIns; private System.Windows.Forms.Button BtnExit; private System.Windows.Forms.Button BtnBack; private System.Windows.Forms.DataGrid dataGrid; private DataSet ResultData; private DataTable tEmp; private DataColumn cEmpNo; private DataColumn cEName; private DataColumn cJob; private DataColumn cMgr; private DataColumn cDate; private DataColumn cSal; private DataColumn cComm; private DataColumn cDept; private System.ComponentModel.Container components = null; public EmployeeMgr() { bTxRun = false; bConnect = false; nSndBuf = 0; nRcvBuf = 0; InitializeComponent(); MakeDataSet(); } private void ErrorProcess(string ErrMsg) { LabelErr.Text = ErrMsg; if( bTxRun == true ) { tx.TX_ROLLBACK(); bTxRun = false; } if( nRcvBuf != 0 ) atmi.TPFREE(ref nRcvBuf); if( nSndBuf != 0 ) atmi.TPFREE(ref nSndBuf); if( bConnect == true ) { atmi.TPEND(); bConnect = false; } } private void SuccessProcess(string SucMsg) { LabelErr.Text = SucMsg; if( bTxRun == true ) { tx.TX_COMMIT(); bTxRun = false; } if( nRcvBuf != 0 ) atmi.TPFREE(ref nRcvBuf); if( nSndBuf != 0 ) atmi.TPFREE(ref nSndBuf); if( bConnect == true ) { atmi.TPEND(); bConnect = false; } } private void ClearWindow() { EditEmpNo.Clear(); EditName.Clear(); EditJob.Clear(); EditMgr.Clear(); EditDate.Clear(); EditSal.Clear(); EditComm.Clear(); EditDept.Clear(); tEmp.Clear(); } private bool TmaxConnect(){ tpstart_t tpinfo = new tpstart_t(); tpinfo.cltname = "star"; tpinfo.usrname = "star"; tpinfo.usrpwd = "star"; tpinfo.dompwd = "star"; tpinfo.flags = atmi.TPUNSOL_IGN; nRcvBuf = atmi.TPALLOC("TPSTART", null, 0); if( nRcvBuf == 0 ) return false; atmi.FilltpstartBuf(ref nRcvBuf, tpinfo); if( atmi.TPSTART(nRcvBuf) == -1 ) return false; return true; } private bool CheckInputData(InputCheck Level) { if(EditEmpNo.Text.Length == 0) return false; if(Level == InputCheck.Pri_Key ) return true; else { if(EditName.Text.Length == 0) return false; if(EditJob.Text.Length == 0) return false; if(EditMgr.Text.Length == 0) return false; if(EditDate.Text.Length != 8) return false; if(EditSal.Text.Length == 0) return false; if(EditComm.Text.Length == 0) return false; if(EditDept.Text.Length == 0) return false; return true; } } private bool PutMyData(InputCheck Level) { int nData; float fData; if(EditEmpNo.Text.Length != 0) { nData = int.Parse(EditEmpNo.Text); if( fdl.FBPUT(nSndBuf,fdl.FBGET_FLDKEY(EmpFKey[0]), ref nData,0)< 0) return false; } if(Level == InputCheck.Pri_Key ) return true; if(EditName.Text.Length != 0) if(fdl.FBPUT(nSndBuf, fdl.FBGET_FLDKEY(EmpFKey[1]), EditName.Text, EditName.Text.Length) < 0) return false; if(EditJob.Text.Length != 0) if(fdl.FBPUT( nSndBuf, fdl.FBGET_FLDKEY(EmpFKey[2]), EditJob.Text, EditJob.Text.Length) < 0 ) return false; if(EditMgr.Text.Length != 0) { nData = int.Parse(EditMgr.Text); if(fdl.FBPUT(nSndBuf,fdl.FBGET_FLDKEY(EmpFKey[3]), ref nData,0)< 0 ) return false; } if(EditDate.Text.Length == 8) if(fdl.FBPUT( nSndBuf, fdl.FBGET_FLDKEY(EmpFKey[4]), EditDate.Text, EditDate.Text.Length) < 0 ) return false; if(EditSal.Text.Length != 0){ fData = float.Parse(EditSal.Text); if(fdl.FBPUT(nSndBuf,fdl.FBGET_FLDKEY(EmpFKey[5]), ref fData,0)< 0 ) return false; } if(EditComm.Text.Length != 0) { fData = float.Parse(EditComm.Text); if(fdl.FBPUT(nSndBuf,fdl.FBGET_FLDKEY(EmpFKey[6]), ref fData,0)< 0 ) return false; } if(EditDept.Text.Length != 0) { nData = int.Parse(EditDept.Text); if(fdl.FBPUT(nSndBuf,fdl.FBGET_FLDKEY(EmpFKey[7]), ref nData,0)< 0) return false; } return true; } private void MakeDataSet() { ResultData = new DataSet("dataGrid"); tEmp = new DataTable("Employee"); cEmpNo = new DataColumn(ColumnName[0],typeof(int));; cEName = new DataColumn(ColumnName[1],typeof(string)); cJob = new DataColumn(ColumnName[2],typeof(string)); cMgr = new DataColumn(ColumnName[3],typeof(int)); cDate = new DataColumn(ColumnName[4],typeof(string)); cSal = new DataColumn(ColumnName[5],typeof(float)); cComm = new DataColumn(ColumnName[6],typeof(float)); cDept = new DataColumn(ColumnName[7],typeof(int)); tEmp.Columns.Add(cEmpNo); tEmp.Columns.Add(cEName); tEmp.Columns.Add(cJob); tEmp.Columns.Add(cMgr); tEmp.Columns.Add(cDate); tEmp.Columns.Add(cSal); tEmp.Columns.Add(cComm); tEmp.Columns.Add(cDept); ResultData.Tables.Add(tEmp); //DataRow newRow1 = tEmp.NewRow(); dataGrid.SetDataBinding(ResultData, "Employee"); } private void ReceiveError() { int nLeng = 0; object[] oEData = new object[ErrFLD_NUM]; for(int i = 0; i < ErrFLD_NUM; i++) { if(fdl.FBGET(nRcvBuf, fdl.FBGET_FLDKEY(ErrFKey[i]), out oEData[i], ref nLeng) < 0 ) break; } ErrorProcess(oEData[2].ToString()); return; } protected override void Dispose( bool disposing ) { if(disposing) { if(components != null) { components.Dispose(); } } base.Dispose( disposing ); } #region Windows Form Designer generated code /*Design*/ … #endregion static void Main() { Application.Run(new EmployeeMgr()); } private void EmployeeMgr_Load(object sender, System.EventArgs e) { const string EnvFile = "D:\\tmax.env"; if(atmi.TMAXREADENV(EnvFile,"TMAX") == -1 ) ErrorProcess("Failed to read a configuration file. -"+ EnvFile); } private void BtnExit_Click(object sender, System.EventArgs e) { Dispose(); } private void BtnIns_Click(object sender, System.EventArgs e) { int nLeng = 0; if(CheckInputData( InputCheck.All ) == false) { ErrorProcess("There is a field with no data.\n Enter 8 characters (YYYYMMDD) for a joining date."); return; } bConnect = TmaxConnect(); if(bConnect == false ) ErrorProcess("Could not connect to a server."); if(bTxRun == false) { if(tx.TX_BEGIN() < 0) { ErrorProcess( "TX_BEGIN Error"); return; } bTxRun = true; } if(nSndBuf != 0 ) atmi.TPFREE(ref nSndBuf); if((nSndBuf = fdl.FBALLOC( 5, 1000) ) == 0 ) ErrorProcess("FBALLOC - Memory allocation error"); if(nRcvBuf != 0 ) atmi.TPFREE(ref nRcvBuf); if((nRcvBuf = fdl.FBALLOC( 5, 1000) ) == 0 ) ErrorProcess("FBALLOC - Memory allocation error"); if(PutMyData( InputCheck.All ) == false) { ErrorProcess("An error occurred during a field key insertion."); return; } if(atmi.TPCALL( "FDLINSERT", nSndBuf, 0, ref nRcvBuf, ref nLeng, atmi.TPNOFLAGS) < 0 ) { ReceiveError(); return; } SuccessProcess( EditEmpNo.Text +" is inserted."); } private void BtnSel_Click(object sender, System.EventArgs e) { int nLeng = 0; object[] oData = new object[FIELD_NUM]; if(CheckInputData( InputCheck.Pri_Key ) == false ) { ErrorProcess("Enter an employee number."); return; } bConnect = TmaxConnect(); if(bConnect == false ) ErrorProcess("Could not connect to a server."); if(bTxRun == false ) { if(tx.TX_BEGIN() < 0 ) { ErrorProcess( "TX_BEGIN Error"); return; } bTxRun = true; } if(nSndBuf != 0 ) atmi.TPFREE(ref nSndBuf); if((nSndBuf = fdl.FBALLOC( 5, 1000) ) == 0 ) ErrorProcess("FBALLOC - Memory allocation error"); if(nRcvBuf != 0) atmi.TPFREE(ref nRcvBuf); if((nRcvBuf = fdl.FBALLOC( 5, 1000)) == 0) ErrorProcess("FBALLOC - Memory allocation error"); if ( PutMyData( InputCheck.Pri_Key ) == false) { ErrorProcess("An error occurred during a field key insertion."); return; } if(atmi.TPCALL("FDLSELECT", nSndBuf, 0, ref nRcvBuf, ref nLeng, atmi.TPNOFLAGS) < 0 ) { ReceiveError(); return; } int OccrN = fdl.FBKEYOCCUR(nRcvBuf,fdl.FBGET_FLDKEY(EmpFKey[0])); for(int j=0; j< OccrNum; j++) { DataRow OutputRow = tEmp.NewRow(); for(int i=0; i< FIELD_NUM; i++) { if(fdl.FBGET_TU( nRcvBuf, fdl.FBGET_FLDKEY(EmpFKey[i]), j, out oData[i], ref nLeng) < 0 ) break; OutputRow[ColumnName[i]] = oData[i]; } tEmp.Rows.Add(OutputRow); } SuccessProcess("Search Result"); dataGrid.Visible = true; BtnBack.Visible = true; dataGrid.RowHeadersVisible = false; } private void BtnUpt_Click(object sender, System.EventArgs e) { int nLeng=0; if(CheckInputData( InputCheck.Pri_Key ) == false ) { ErrorProcess("There is a field with no data.\n Enter 8 characters (YYYYMMDD) for a joining date."); return; } bConnect = TmaxConnect(); if(bConnect == false ) ErrorProcess("Could not connect to a server."); if( bTxRun == false ) { if(tx.TX_BEGIN() < 0 ) { ErrorProcess( "TX_BEGIN Error"); return; } bTxRun = true; } if(nSndBuf != 0 ) atmi.TPFREE(ref nSndBuf); if((nSndBuf = fdl.FBALLOC( 5, 1000) ) == 0 ) ErrorProcess("FBALLOC - Memory allocation error"); if(nRcvBuf != 0 ) atmi.TPFREE(ref nRcvBuf); if((nRcvBuf = fdl.FBALLOC( 5, 1000) ) == 0 ) ErrorProcess("FBALLOC - Memory allocation error"); if(PutMyData( InputCheck.All ) == false) { ErrorProcess("An error occurred during a field key insertion."); return; } if(atmi.TPCALL("FDLUPDATE", nSndBuf, 0, ref nRcvBuf, ref nLeng, atmi.TPNOFLAGS) < 0 ) { ReceiveError(); return; } SuccessProcess(EditEmpNo.Text + "is modified."); ClearWindow(); } private void BtnDel_Click(object sender, System.EventArgs e) { int nLeng = 0; if( CheckInputData( InputCheck.Pri_Key ) == false ) { ErrorProcess("Enter an employee number."); return; } bConnect = TmaxConnect(); if( bConnect == false ) ErrorProcess("Could not connect to a server."); if( bTxRun == false ) { if( tx.TX_BEGIN() < 0 ) { ErrorProcess( "TX_BEGIN Error"); return; } bTxRun = true; } if( nSndBuf != 0 ) atmi.TPFREE(ref nSndBuf); if( ( nSndBuf = fdl.FBALLOC( 5, 1000) ) == 0 ) ErrorProcess("FBALLOC - Memory allocation error"); if( nRcvBuf != 0 ) atmi.TPFREE(ref nRcvBuf); if( ( nRcvBuf = fdl.FBALLOC( 5, 1000) ) == 0 ) ErrorProcess("FBALLOC - Memory allocation error"); if( PutMyData( InputCheck.Pri_Key ) == false ) { ErrorProcess("An error occurred during a field Key insertion."); return; } if(atmi.TPCALL("FDLDELETE", nSndBuf, 0, ref nRcvBuf, ref nLeng, atmi.TPNOFLAGS) < 0) { ReceiveError(); return; } SuccessProcess( EditEmpNo.Text + "has been deleted."); ClearWindow(); } private void BtnBack_Click(object sender, System.EventArgs e) { dataGrid.Visible = false; BtnBack.Visible = false; ClearWindow(); } }
The following is an example of Unicode (UTF-8) programming source for managing employees.
In general, it does not have to set anything but Atmi.SetServerEncoding (Encoding.UTF8). However, if a client uses a separate encoding, set the encoding by using SetClientEncoding(). To support 64-bit encoding, nSndBuf and nRcvBuf are declared as IntPtr instead of int.
<Form1.cs>
using System; using System.Drawing; using System.Collections; using System.ComponentModel; using System.Windows.Forms; using System.Data; using AtmiNS; using WinApiNS; using FdlNS; using TxNS; using TmaxApiNS; namespace _4GL_Sample { public class EmployeeMgr : System.Windows.Forms.Form { Atmi.SetServerEncoding(Encoding.UTF8); private Atmi atmi = new Atmi(); private WinApi winApi = new WinApi(); private Fdl fdl = new Fdl(); private Tx tx = new Tx(); private TmaxApi tmaxApi = new TmaxApi(); bool bTxRun, bConnect; IntPtr nSndBuf, nRcvBuf; public string[] EmpFKey = {"EMPNO","ENAME","JOB","MGR","DATE","SAL","COMM","DEPTNO"}; public string[] ErrFKey = {"E_TYPE","E_CODE","E_MSG","E_TMP"}; public string[] ColumnName = {"EmpNo","Name","Position","Mgr","JoinDate","Salary","COMM","Dept"}; public const int FIELD_NUM = 8; public const int ErrFLD_NUM = 4; public enum InputCheck { Pri_Key, All }; private System.Windows.Forms.Label label1; private System.Windows.Forms.Label label2; private System.Windows.Forms.Label label3; private System.Windows.Forms.Label label4; private System.Windows.Forms.Label label5; private System.Windows.Forms.Label label6; private System.Windows.Forms.Label label7; private System.Windows.Forms.Label label8; private System.Windows.Forms.GroupBox groupBox1; private System.Windows.Forms.TextBox EditEmpNo; private System.Windows.Forms.TextBox EditName; private System.Windows.Forms.TextBox EditJob; private System.Windows.Forms.TextBox EditMgr; private System.Windows.Forms.TextBox EditDate; private System.Windows.Forms.TextBox EditSal; private System.Windows.Forms.TextBox EditComm; private System.Windows.Forms.TextBox EditDept; private System.Windows.Forms.Label LabelErr; private System.Windows.Forms.Button BtnSel; private System.Windows.Forms.Button BtnUpt; private System.Windows.Forms.Button BtnDel; private System.Windows.Forms.Button BtnIns; private System.Windows.Forms.Button BtnExit; private System.Windows.Forms.Button BtnBack; private System.Windows.Forms.DataGrid dataGrid; private DataSet ResultData; private DataTable tEmp; private DataColumn cEmpNo; private DataColumn cEName; private DataColumn cJob; private DataColumn cMgr; private DataColumn cDate; private DataColumn cSal; private DataColumn cComm; private DataColumn cDept; private System.ComponentModel.Container components = null; public EmployeeMgr() { bTxRun = false; bConnect = false; nSndBuf = IntPtr.Zero; nRcvBuf = IntPtr.Zero; InitializeComponent(); MakeDataSet(); } private void ErrorProcess(string ErrMsg) { LabelErr.Text = ErrMsg; if( bTxRun == true ) { tx.TX_ROLLBACK(); bTxRun = false; } if( nRcvBuf != IntPtr.Zero ) atmi.TPFREE(ref nRcvBuf); if( nSndBuf != IntPtr.Zero ) atmi.TPFREE(ref nSndBuf); if( bConnect == true ) { atmi.TPEND(); bConnect = false; } } private void SuccessProcess(string SucMsg) { LabelErr.Text = SucMsg; if( bTxRun == true ) { tx.TX_COMMIT(); bTxRun = false; } if( nRcvBuf != IntPtr.Zero ) atmi.TPFREE(ref nRcvBuf); if( nSndBuf != IntPtr.Zero ) atmi.TPFREE(ref nSndBuf); if( bConnect == true ) { atmi.TPEND(); bConnect = false; } } private void ClearWindow() { EditEmpNo.Clear(); EditName.Clear(); EditJob.Clear(); EditMgr.Clear(); EditDate.Clear(); EditSal.Clear(); EditComm.Clear(); EditDept.Clear(); tEmp.Clear(); } private bool TmaxConnect(){ tpstart_t tpinfo = new tpstart_t(); tpinfo.cltname = "star"; tpinfo.usrname = "star"; tpinfo.usrpwd = "star"; tpinfo.dompwd = "star"; tpinfo.flags = atmi.TPUNSOL_IGN; nRcvBuf = atmi.TPALLOC("TPSTART", null, 0); if( nRcvBuf == IntPtr.Zero) return false; atmi.FilltpstartBuf(ref nRcvBuf, tpinfo); if( atmi.TPSTART(nRcvBuf) == -1 ) return false; return true; } private bool CheckInputData(InputCheck Level) { if(EditEmpNo.Text.Length == 0) return false; if(Level == InputCheck.Pri_Key ) return true; else { if(EditName.Text.Length == 0) return false; if(EditJob.Text.Length == 0) return false; if(EditMgr.Text.Length == 0) return false; if(EditDate.Text.Length != 8) return false; if(EditSal.Text.Length == 0) return false; if(EditComm.Text.Length == 0) return false; if(EditDept.Text.Length == 0) return false; return true; } } private bool PutMyData(InputCheck Level) { int nData; float fData; if(EditEmpNo.Text.Length != 0) { nData = int.Parse(EditEmpNo.Text); if( fdl.FBPUT(nSndBuf,fdl.FBGET_FLDKEY(EmpFKey[0]), ref nData,0)< 0) return false; } if(Level == InputCheck.Pri_Key ) return true; if(EditName.Text.Length != 0) if(fdl.FBPUT(nSndBuf, fdl.FBGET_FLDKEY(EmpFKey[1]), EditName.Text, EditName.Text.Length) < 0) return false; if(EditJob.Text.Length != 0) if(fdl.FBPUT( nSndBuf, fdl.FBGET_FLDKEY(EmpFKey[2]), EditJob.Text, EditJob.Text.Length) < 0 ) return false; if(EditMgr.Text.Length != 0) { nData = int.Parse(EditMgr.Text); if(fdl.FBPUT(nSndBuf,fdl.FBGET_FLDKEY(EmpFKey[3]), ref nData,0)< 0 ) return false; } if(EditDate.Text.Length == 8) if(fdl.FBPUT( nSndBuf, fdl.FBGET_FLDKEY(EmpFKey[4]), EditDate.Text, EditDate.Text.Length) < 0 ) return false; if(EditSal.Text.Length != 0){ fData = float.Parse(EditSal.Text); if(fdl.FBPUT(nSndBuf,fdl.FBGET_FLDKEY(EmpFKey[5]), ref fData,0)< 0 ) return false; } if(EditComm.Text.Length != 0) { fData = float.Parse(EditComm.Text); if(fdl.FBPUT(nSndBuf,fdl.FBGET_FLDKEY(EmpFKey[6]), ref fData,0)< 0 ) return false; } if(EditDept.Text.Length != 0) { nData = int.Parse(EditDept.Text); if(fdl.FBPUT(nSndBuf,fdl.FBGET_FLDKEY(EmpFKey[7]), ref nData,0)< 0) return false; } return true; } private void MakeDataSet() { ResultData = new DataSet("dataGrid"); tEmp = new DataTable("Employee"); cEmpNo = new DataColumn(ColumnName[0],typeof(int));; cEName = new DataColumn(ColumnName[1],typeof(string)); cJob = new DataColumn(ColumnName[2],typeof(string)); cMgr = new DataColumn(ColumnName[3],typeof(int)); cDate = new DataColumn(ColumnName[4],typeof(string)); cSal = new DataColumn(ColumnName[5],typeof(float)); cComm = new DataColumn(ColumnName[6],typeof(float)); cDept = new DataColumn(ColumnName[7],typeof(int)); tEmp.Columns.Add(cEmpNo); tEmp.Columns.Add(cEName); tEmp.Columns.Add(cJob); tEmp.Columns.Add(cMgr); tEmp.Columns.Add(cDate); tEmp.Columns.Add(cSal); tEmp.Columns.Add(cComm); tEmp.Columns.Add(cDept); ResultData.Tables.Add(tEmp); //DataRow newRow1 = tEmp.NewRow(); dataGrid.SetDataBinding(ResultData, "Employee"); } private void ReceiveError() { int nLeng = 0; object[] oEData = new object[ErrFLD_NUM]; for(int i = 0; i < ErrFLD_NUM; i++) { if(fdl.FBGET(nRcvBuf, fdl.FBGET_FLDKEY(ErrFKey[i]), out oEData[i], ref nLeng) < 0 ) break; } ErrorProcess(oEData[2].ToString()); return; } protected override void Dispose( bool disposing ) { if(disposing) { if(components != null) { components.Dispose(); } } base.Dispose( disposing ); } #region Windows Form Designer generated code /*Design*/ … #endregion static void Main() { Application.Run(new EmployeeMgr()); } private void EmployeeMgr_Load(object sender, System.EventArgs e) { const string EnvFile = "D:\\tmax.env"; if(atmi.TMAXREADENV(EnvFile,"TMAX") == -1 ) ErrorProcess("Failed to read a configuration file. -"+ EnvFile); } private void BtnExit_Click(object sender, System.EventArgs e) { Dispose(); } private void BtnIns_Click(object sender, System.EventArgs e) { int nLeng = 0; if(CheckInputData( InputCheck.All ) == false) { ErrorProcess("There is a field with no data.\n Enter 8 characters (YYYYMMDD) for a joining date."); return; } bConnect = TmaxConnect(); if(bConnect == false ) ErrorProcess("Could not connect to a server."); if(bTxRun == false) { if(tx.TX_BEGIN() < 0) { ErrorProcess( "TX_BEGIN Error"); return; } bTxRun = true; } if(nSndBuf != IntPtr.Zero ) atmi.TPFREE(ref nSndBuf); if((nSndBuf = fdl.FBALLOC( 5, 1000) ) == IntPtr.Zero ) ErrorProcess("FBALLOC - Memory allocation error"); if(nRcvBuf != IntPtr.Zero ) atmi.TPFREE(ref nRcvBuf); if((nRcvBuf = fdl.FBALLOC( 5, 1000) ) == IntPtr.Zero ) ErrorProcess("FBALLOC - Memory allocation error"); if(PutMyData( InputCheck.All ) == false) { ErrorProcess("An error occurred during a field Key insertion."); return; } if(atmi.TPCALL( "FDLINSERT", nSndBuf, 0, ref nRcvBuf, ref nLeng, atmi.TPNOFLAGS) < 0 ) { ReceiveError(); return; } SuccessProcess( EditEmpNo.Text +"is inserted."); } private void BtnSel_Click(object sender, System.EventArgs e) { int nLeng = 0; object[] oData = new object[FIELD_NUM]; if(CheckInputData( InputCheck.Pri_Key ) == false ) { ErrorProcess("Enter an employee number."); return; } bConnect = TmaxConnect(); if(bConnect == false ) ErrorProcess("Could not connect to a server."); if(bTxRun == false ) { if(tx.TX_BEGIN() < 0 ) { ErrorProcess( "TX_BEGIN Error"); return; } bTxRun = true; } if(nSndBuf != IntPtr.Zero ) atmi.TPFREE(ref nSndBuf); if((nSndBuf = fdl.FBALLOC( 5, 1000) ) == IntPtr.Zero ) ErrorProcess("FBALLOC - Memory allocation error"); if(nRcvBuf != IntPtr.Zero) atmi.TPFREE(ref nRcvBuf); if((nRcvBuf = fdl.FBALLOC( 5, 1000)) == IntPtr.Zero) ErrorProcess("FBALLOC - Memory allocation error"); if ( PutMyData( InputCheck.Pri_Key ) == false) { ErrorProcess("An error occurred during a field Key insertion."); return; } if(atmi.TPCALL("FDLSELECT", nSndBuf, 0, ref nRcvBuf, ref nLeng, atmi.TPNOFLAGS) < 0 ) { ReceiveError(); return; } int OccrN = fdl.FBKEYOCCUR(nRcvBuf,fdl.FBGET_FLDKEY(EmpFKey[0])); for(int j=0; j< OccrNum; j++) { DataRow OutputRow = tEmp.NewRow(); for(int i=0; i< FIELD_NUM; i++) { if(fdl.FBGET_TU( nRcvBuf, fdl.FBGET_FLDKEY(EmpFKey[i]), j, out oData[i], ref nLeng) < 0 ) break; OutputRow[ColumnName[i]] = oData[i]; } tEmp.Rows.Add(OutputRow); } SuccessProcess("Search Result"); dataGrid.Visible = true; BtnBack.Visible = true; dataGrid.RowHeadersVisible = false; } private void BtnUpt_Click(object sender, System.EventArgs e) { int nLeng=0; if(CheckInputData( InputCheck.Pri_Key ) == false ) { ErrorProcess("There is a field with no data.\n Enter 8 characters (YYYYMMDD) for a joining date."); return; } bConnect = TmaxConnect(); if(bConnect == false ) ErrorProcess("Could not connect to a server."); if( bTxRun == false ) { if(tx.TX_BEGIN() < 0 ) { ErrorProcess( "TX_BEGIN Error"); return; } bTxRun = true; } if(nSndBuf != IntPtr.Zero ) atmi.TPFREE(ref nSndBuf); if((nSndBuf = fdl.FBALLOC( 5, 1000) ) == IntPtr.Zero ) ErrorProcess("FBALLOC - Memory allocation error"); if(nRcvBuf != IntPtr.Zero ) atmi.TPFREE(ref nRcvBuf); if((nRcvBuf = fdl.FBALLOC( 5, 1000) ) == IntPtr.Zero ) ErrorProcess("FBALLOC - Memory allocation error"); if(PutMyData( InputCheck.All ) == false) { ErrorProcess("An error occurred during a field Key insertion."); return; } if(atmi.TPCALL("FDLUPDATE", nSndBuf, 0, ref nRcvBuf, ref nLeng, atmi.TPNOFLAGS) < 0 ) { ReceiveError(); return; } SuccessProcess(EditEmpNo.Text + "is modified."); ClearWindow(); } private void BtnDel_Click(object sender, System.EventArgs e) { int nLeng = 0; if( CheckInputData( InputCheck.Pri_Key ) == false ) { ErrorProcess("Enter an employee number."); return; } bConnect = TmaxConnect(); if( bConnect == false ) ErrorProcess("Could not connect to a server."); if( bTxRun == false ) { if( tx.TX_BEGIN() < 0 ) { ErrorProcess( "TX_BEGIN Error"); return; } bTxRun = true; } if( nSndBuf != IntPtr.Zero ) atmi.TPFREE(ref nSndBuf); if( ( nSndBuf = fdl.FBALLOC( 5, 1000) ) == IntPtr.Zero ) ErrorProcess("FBALLOC - Memory allocation error"); if( nRcvBuf != IntPtr.Zero ) atmi.TPFREE(ref nRcvBuf); if( ( nRcvBuf = fdl.FBALLOC( 5, 1000) ) == IntPtr.Zero ) ErrorProcess("FBALLOC - Memory allocation error"); if( PutMyData( InputCheck.Pri_Key ) == false ) { ErrorProcess("An error occurred during a field Key insertion."); return; } if(atmi.TPCALL("FDLDELETE", nSndBuf, 0, ref nRcvBuf, ref nLeng, atmi.TPNOFLAGS) < 0) { ReceiveError(); return; } SuccessProcess( EditEmpNo.Text + "has been deleted."); ClearWindow(); } private void BtnBack_Click(object sender, System.EventArgs e) { dataGrid.Visible = false; BtnBack.Visible = false; ClearWindow(); } }
2.5. Server Program
Service Program
The following is an example service program.
<emp_c.pc>
#include <stdio.h> #include <ctype.h> #include <tuxinc/macro.h> #include "../../fdl/demo_fdl.h" EXEC SQL include sqlca.h; EXEC SQL INCLUDE ORACA; EXEC ORACLE OPTION (ORACA=YES); EXEC ORACLE OPTION (RELEASE_CURSOR=YES); #define INP 1 #define ORA 2 #define TMX 3 #define APP 4 EXEC SQL begin declare section; int h_empno; char h_ename[11]; char h_job[10]; int h_mgr; char h_date[11]; float h_sal; float h_comm; int h_deptno; EXEC SQL end declare section; void svc_error(long type, long err_code, char *msg, long tmp); FDLINSERT( TPSVCINFO *msg ) { FBUF *rcvbuf; int i, occurrence; rcvbuf = (FBUF *)msg->data; h_empno = h_mgr = h_sal = h_comm = h_deptno = 0; memset( h_ename, 0x00, sizeof( h_ename ) ); memset( h_job, 0x00, sizeof( h_job ) ); memset( h_date, 0x00, sizeof( h_date ) ); occurrence = fbkeyoccur(rcvbuf, EMPNO); for (i=0; i< occurrence; i++){ fbget_tu (rcvbuf, EMPNO, i, (char *)&h_empno, 0); fbget_tu (rcvbuf, MGR, i, (char *)&h_mgr, 0); fbget_tu (rcvbuf, SAL, i, (char *)&h_sal, 0); fbget_tu (rcvbuf, COMM, i, (char *)&h_comm, 0); fbget_tu (rcvbuf, DEPTNO,i, (char *)&h_deptno, 0); fbget_tu (rcvbuf, ENAME, i, (char *)h_ename, 0); fbget_tu (rcvbuf, JOB , i, (char *)h_job, 0); fbget_tu (rcvbuf, DATE , i, (char *)h_date, 0); EXEC SQL INSERT INTO emp(empno, ename, job, mgr, hiredate, sal,comm, deptno) VALUES (:h_empno, :h_ename, :h_job, :h_mgr, to_date(:h_date,'yyyymmdd'), :h_sal, :h_comm, :h_deptno); } if(sqlca.sqlcode != 0) goto LB_DBERROR; EXEC SQL WHENEVER SQLERROR goto LB_DBERROR; tpreturn(TPSUCCESS, 0L, (char *)rcvbuf, 0L, 0L); LB_DBERROR : EXEC SQL WHENEVER SQLERROR CONTINUE; svc_error(ORA, sqlca.sqlcode, sqlca.sqlerrm.sqlerrmc, 0) ; } FDLDELETE( TPSVCINFO *msg ) { FBUF *rcvbuf; int i, occurrence; rcvbuf = ( FBUF *)msg->data; occurrence = fbkeyoccur(rcvbuf, EMPNO); for (i=0; i< occurrence; i++){ fbget_tu (rcvbuf, EMPNO, i, (char *)&h_empno , 0); EXEC SQL DELETE FROM emp WHERE empno = :h_empno; } if(sqlca.sqlcode != 0) goto LB_DBERROR; EXEC SQL WHENEVER SQLERROR goto LB_DBERROR; EXEC SQL WHENEVER NOT FOUND goto LB_DBERROR; tpreturn(TPSUCCESS, 0L, (char *)rcvbuf, 0L, 0L); LB_DBERROR : EXEC SQL WHENEVER SQLERROR CONTINUE; svc_error(ORA, sqlca.sqlcode, sqlca.sqlerrm.sqlerrmc, 0); } FDLSELECT( TPSVCINFO *msg ) { FBUF *rcvbuf; FLDLEN fldlen; int i=0, ROWMEM=200, CHKROW=500; rcvbuf = (FBUF *)msg->data; if((rcvbuf=(FBUF *)tprealloc((char *)rcvbuf,ROWMEM*CHKROW))==NULL){ rcvbuf=(FBUF *)msg->data; goto LB_TMAXERROR ; } h_empno = h_mgr = h_sal = h_comm = h_deptno = 0; memset( h_ename, 0x00, sizeof( h_ename ) ); memset( h_job, 0x00, sizeof( h_job ) ); memset( h_date, 0x00, sizeof( h_date ) ); fbget_tu( rcvbuf, EMPNO, 0, (char *)&h_empno, &fldlen); EXEC SQL DECLARE DB_CUR CURSOR FOR SELECT nvl(empno,0), nvl(ename,' '), nvl(job,' '), nvl(to_char(hiredate,'yyyymmdd'),' '), nvl(mgr,0), nvl(sal,0), nvl(comm,0), nvl(deptno,0) FROM emp WHERE empno >= :h_empno-50 AND empno <= :h_empno+50; EXEC SQL OPEN DB_CUR; if(sqlca.sqlcode != 0) goto LB_DBERROR; EXEC SQL WHENEVER SQLERROR goto LB_DBERROR ; EXEC SQL WHENEVER NOT FOUND Do break ; while(1) { EXEC SQL FETCH DB_CUR INTO :h_empno, :h_ename, :h_job, :h_date, :h_mgr, :h_sal, :h_comm, :h_deptno; fbchg_tu(rcvbuf, EMPNO, i,(char *)&h_empno, 0); fbchg_tu(rcvbuf, MGR, i,(char *)&h_mgr, 0); fbchg_tu(rcvbuf, SAL, i,(char *)&h_sal, 0); fbchg_tu(rcvbuf, DEPTNO, i,(char *)&h_deptno, 0); fbchg_tu(rcvbuf, COMM, i,(char *)&h_comm, 0); fbchg_tu(rcvbuf, ENAME, i,(char *)h_ename, 0); fbchg_tu(rcvbuf, JOB, i,(char *)h_job, 0); fbchg_tu(rcvbuf, DATE, i,(char *)h_date, 0); i++; } if (i < 1) goto LB_DBERROR; EXEC SQL CLOSE DB_CUR; tpreturn(TPSUCCESS, 0L, (char *)rcvbuf, 0L, 0L); LB_DBERROR : EXEC SQL WHENEVER SQLERROR CONTINUE; EXEC SQL CLOSE DB_CUR ; svc_error(ORA, sqlca.sqlcode, sqlca.sqlerrm.sqlerrmc, 0L) ; LB_TMAXERROR : EXEC SQL WHENEVER SQLERROR CONTINUE; EXEC SQL CLOSE DB_CUR ; svc_error(TMX, tperrno, "", 0L) ; } FDLUPDATE( TPSVCINFO *msg ) { FBUF *rcvbuf ; int i, occurrence; rcvbuf = (FBUF *)msg->data; h_empno = h_mgr = h_sal = h_comm = h_deptno = 0; memset( h_ename, 0x00, sizeof( h_ename ) ); memset( h_job, 0x00, sizeof( h_job ) ); memset( h_date, 0x00, sizeof( h_date ) ); occurrence = fbkeyoccur(rcvbuf, EMPNO); for (i=0; i< occurrence; i++) { fbget_tu (rcvbuf, EMPNO, i, (char *)&h_empno, 0); fbget_tu (rcvbuf, ENAME, i, (char *)h_ename, 0); fbget_tu (rcvbuf, JOB, i, (char *)h_job, 0); fbget_tu (rcvbuf, MGR, i, (char *)&h_mgr, 0); fbget_tu (rcvbuf, SAL, i, (char *)&h_sal, 0); fbget_tu (rcvbuf, COMM, i, (char *)&h_comm,0); fbget_tu (rcvbuf, DEPTNO, i, (char *)&h_deptno,0); fbget_tu (rcvbuf, DATE, i, (char *)h_date, 0 ); EXEC SQL UPDATE emp SET ename = nvl(:h_ename, ename), job = nvl(:h_job, job), mgr = :h_mgr, hiredate = nvl(to_date(:h_date,'yyyymmdd'),hiredate), sal = :h_sal, comm = :h_comm, deptno = :h_deptno WHERE empno = :h_empno; if(sqlca.sqlcode != 0) goto LB_DBERROR; EXEC SQL WHENEVER SQLERROR goto LB_DBERROR; EXEC SQL WHENEVER NOT FOUND goto LB_DBERROR; } tpreturn(TPSUCCESS, 0L, (char *)rcvbuf, 0L, 0L); LB_DBERROR : EXEC SQL WHENEVER SQLERROR CONTINUE; svc_error(ORA, sqlca.sqlcode, sqlca.sqlerrm.sqlerrmc, 0L) ; } /********************************************************************* * Error Handling: If a service error occurs, the error will be entered in a buffer and then sent to a client. ********************************************************************/ void svc_error(long type, long err_code, char *msg,long tmp) { FBUF *transf; char *svcname; char err_msg[100]; char temp[100]; int i = 0; printf("type ==>[%ld]\n", type); printf("err_code ==>[%ld]\n", err_code); printf("msg ==>[%s]\n", msg); strcpy(err_msg, msg); if((transf = (FBFR *)tpalloc("FML", NULL, 0)) == NULL) { printf("tpalloc failed! errno = %d\n", tperrno); } switch(type) { case INP: switch(err_code) { case -1000: strcpy(err_msg, "The user has no privilege."); break; default: strcpy(err_msg, "An input error message has not been registered."); } break; case ORA: if(strlen(err_msg)== 0) strcpy(err_msg, sqlca.sqlerrm.sqlerrmc); break; case TMX: if(strlen(err_msg)== 0) strcpy(err_msg, tpstrerror(tperrno)); break; case APP: if(strlen(err_msg)== 0) { /* An error message is set. ******/ switch(err_code) { case -500: /* SYSTEM error */ strcpy(err_msg, "Failed to create a file."); break; case -502: strcpy(err_msg, "Could not call an internal service."); break; case -504: strcpy(err_msg, "Socket communication error."); break; case -505: /* When a change was made in another transaction */ /* "[%s] was changed in another transaction after it was queried. \n\nHandle it after querying it again.": Handling in CLIENT */ strcpy(err_msg,"does not exist."); break; case -5002: strcpy(err_msg, "Contact with a technical team."); break; default: strcpy(err_msg, "An application error message has not been registered."); } } break; } /* ROLLBACK */ EXEC SQL WHENEVER SQLERROR CONTINUE; EXEC SQL ROLLBACK; fbchg_tu (transf, E_TYPE, i, (char *)&type,0); fbchg_tu (transf, E_CODE, i, (char *)&err_code,0); fbchg_tu (transf, E_MSG, i, (char *)err_msg,0); fbchg_tu (transf, E_TMP, i, (char *)&tmp,0); tpreturn(TPFAIL, 0, (char *)transf, 0L, 0L); }
Makefile
The following is an example Makefile that builds emp_c.pc into a Tmax application.
<emp_c.mk>
include $(ORACLE_HOME)/precomp/lib/env32.mk ORALIBDIR = $(LIBHOME) ORALIB = -L/home/oracle/OraHome/lib32/ -lclntsh -lld -lm `cat /home/oracle/OraHome/lib32/sysliblist` -lm -lc_r -lpthreads TARGET = emp_c APOBJS = emp_c.o NSDLOBJ = $(TMAXDIR)/lib/sdl.o #CC CC=cc #Oracle LIBS = -lsvr -loras OBJS = $(APOBJS) $(SVCTOBJ) SVCTOBJ = $(TARGET)_svctab.o CFLAGS = -q32 -O -I$(TMAXDIR) LDFLAGS = -brtl APPDIR = $(TMAXDIR)/appbin SVCTDIR = $(TMAXDIR)/svct TMAXLIBDIR = $(TMAXDIR)/lib # .SUFFIXES : .c .c.o: $(CC) $(CFLAGS) $(LDFLAGS) -c $< all: $(TARGET) $(TARGET): $(OBJS) $(CC) $(CFLAGS) $(LDFLAGS) -L$(TMAXLIBDIR) -o $(TARGET) -L$(ORALIBDIR) $(ORALIB) $(OBJS) $(LIBS) $(NSDLOBJ) mv $(TARGET) $(TMAXDIR)/appbin $(APOBJS): $(TARGET).pc proc iname=emp_c include=$(TMAXDIR) define=__LINUX_ORACLE_PROC__ $(CC) $(CFLAGS) $(LDFLAGS) -c $(TARGET).c $(SVCTOBJ): touch $(SVCTDIR)/$(TARGET)_svctab.c $(CC) $(CFLAGS) $(LDFLAGS) -c $(SVCTDIR)/$(TARGET)_svctab.c #clean: -rm -f *.o core $(TARGET) $(TARGET).lis