Dot Net Fluke: Getting by on C# for iSeries RPG Developers

Useful tutorials on C# and .NET for RPG iSeries AS/400 developers. Brought to you from the folks at AranRock Consulting

3/18/08

C# Subfile - iSeries data in a C# Grid -2 no coding (with Video)

Well almost no coding.

If you look at my previous post where I showed how to code a grid in C# using data from the iSeries we manually coded the grid, the data set and the connection. This example accomplishes the same result except you'll be done in under 5 minutes!  It uses the IDE to build the grid, data set, adapter, connection and SQL command.

The video also shows how to add in the iSeries .net data components to your Visual Studio toolbox.
This post easier shown than discussed - so check out the following video.
play

Steps

  1. Create a windows form application project
  2. Add in the IBM dll to your references
  3. Add in the IBM data tools to your toolbox using Tools, Choose Toolbox items and filter 'idb2'
  4. Add a basic grid to your form
  5. Drag the iDB2Connection, IDB2Command, iDB2DataAdapter and a data set to your form
  6. Configure each by right clicking and selecting properties
  7. Double click outside the grid to bring up the code for the Load method of the form.
  8. Add in the following code
    iDB2DataAdapter1.Fill(dataSet1);
    dataGrid1.DataMember = dataSet1.Tables[0].TableName;
  9. Run the program!

Labels: , , , , , ,

3/17/08

C# Subfile - Display an iSeries table in a Grid

We're all used to subfiles on the iSeries. Who can fondly recall many a debate over page by page vs. load all subfile?   How do you create the equivalent of a subfile in .Net?

Easy.

images

Download the visual studio project from here.

subfile

Here's a basic example to get started. The Visual Studio IDE can actually do a lot of the work for you. You can even create a grid (read subfile) with just one or two lines of code. (Post to come)  However, it's more prudent to begin with code you can understand rather than wading through what looks like binary spaghetti.

This example also introduces data sets and data tables. Data sets are just like data structures but without any definition and data tables are just like the field definitions of data structures -not to be confused with tables in databases. We use Data sets and data tables to disconnect from the data source. Connect to the data source, get the data, fill the data set with the data, disconnect from the data source and use the data set in lieu of the actual data. Another way to think of data sets is to think of them as a cache, bucket, container, plastic bag. See my earlier post on data sets for more info.

 

Steps

  1. Define your grid (i.e. subfile)
  2. Attach the grid to your form (VS creates one for you auto-)
  3. Create a data set to hold your data
  4. Create a data table to define the fields in the data set
  5. Add the data table to the data set
  6. Connect  to your iSeries
  7. Execute an SQL statement to read from a table
  8. Read each row and add to the data set
  9. Disconnect from the iSeries
  10. Attach the data set to the grid
  11. Display the grid

It sounds like a lot of work just to output data to a grid - and it is. Why bother with the data set and the table - can't I just write directly out the grid? Yes you can - but this example is here to show you not only how to display data in a grid from the iSeries but how to best manage that data as well. A Data Set will help you do that. 
It is true that there are much simpler approaches on the iSeries but that comes at a price. Once you get out of the db2 and green screen box things get quite tricky on the As/400.  .Net is more complicated yes but its complexity comes from flexibility.

iSeries prerequisites:

The table on the iSeries in this example is called customers. Create it in library QGPL
create the table in DDS or go into SQL by typing 'strsql' in the iSeries command prompt and create the table as follows:

CREATE TABLE QGPL/CUSTOMERS (NAME CHAR (30 ) NOT NULL WITH DEFAULT,
BALANCE DEC (5 ) NOT NULL WITH DEFAULT)

Add records using the INSERT sql command, DBU or your favorite data editor on the iSeries

C# Code:

This is the code for the form. The 'Program.cs' in solution explorer is unchanged. Simply create a windows project, double click on the form that appears and replace all the code with the code below. Insert your iSeries IP address and make sure you have created the iSeries table as describe above or replace with your own ensuring that you correctly specify the columns.  

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using IBM.Data.DB2.iSeries; // Make sure you add this under 'References' in Solution Explorer
// You need the above reference as a dll which is part of iSeries client access.

namespace iSeries_Grid
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }

        private void Form1_Load(object sender, EventArgs e)
        {
            //Define the grid size
            DataGrid subfile = new DataGrid();
            subfile.Location = new Point(0, 0);
            subfile.Size = new Size(400, 500);

            //Attach it to the form
            Controls.AddRange(new Control[] { subfile });


            // Create a DataSet to hold data from iSeries Table
            DataSet dataStructure = new DataSet();

            //Create a table to hold the iSeries data
            DataTable dt = new DataTable("Customers");
            dt.Columns.Add("Name");
            dt.Columns.Add("Balance");


            //Add the datatable to the data set
            dataStructure.Tables.Add(dt);

            // Open connection to the iSeries
            iDB2Connection conn = new iDB2Connection();
           conn.ConnectionString = "DataSource=192.168.0.1";

 // You can put "UserID=myuserid;Password=mypass" 
//
if you don't want to be prompted

// Create a command to select records from the customer table
iDB2Command command = new iDB2Command();
command.CommandText = "Select * from qgpl.customers";
command.Connection = conn;
// ties the command to the connection to the iSeries

conn.Open();

// Execute the sql statement. Get a Data Reader object
iDB2DataReader readFile = command.ExecuteReader();

// Read each row from the table and output the results into the data set

while (readFile.Read())
{
// Create a row to hold data
DataRow datarow = dataStructure.Tables["customers"].NewRow();

datarow["Name"] = readFile.GetString(0);
datarow["Balance"] = readFile.GetiDB2Integer(1);

// add the row to the data table customer
dataStructure.Tables["customers"].Rows.Add(datarow);


}

// Clean up - Close connections
readFile.Close();
command.Dispose();
conn.Close();

// Attach the data set to the data grid
subfile.DataSource = dataStructure;
subfile.DataMember = dataStructure.Tables[0].TableName;



// Display the subfile
subfile.Show();


} // End of Method


} //End of Class

} // End of Namespace



 



This code is based on an example in the IBM .Net Redbook modified

for this post.

Labels: , , , , ,

3/16/08

Reading an iSeries table in C# (with video)

Here's another simple example of reading a table in C# from the iSeries.
vid  See the video for this here. 

images

   Download the Visual Studio Project here

As you can see (line 13)  all you need in the connection string is the IP address of your machine. If you don't include the log on parameters -UserID=myuser; Password=mypass, then you will be prompted for them by the iSeries.
You need to include the IBM .net provider in your 'References' in your Visual Studio project. It's located in the Client Access directory. If you don't have client access, then download the 'technology preview' from IBM for free.

   1:  using System;


   2:  using System.Collections.Generic;


   3:  using System.Text;


   4:  using IBM.Data.DB2.iSeries;


   5:   


   6:  namespace Prez_Rank


   7:  {


   8:      class Program


   9:      {


  10:          static void Main(string[] args)


  11:          {


  12:              iDB2Connection conn = new iDB2Connection();


  13:              conn.ConnectionString = "DataSource=192.168.0.1";


  14:              conn.Open();


  15:   


  16:              iDB2Command cmd = new iDB2Command();


  17:              cmd.CommandText = "Select * from colm.customers";


  18:              cmd.Connection = conn;


  19:   


  20:   


  21:   


  22:              iDB2DataReader dr= cmd.ExecuteReader();


  23:   


  24:              while (dr.Read())


  25:              {


  26:                  Console.WriteLine(dr.GetString(0));


  27:   


  28:              }


  29:              Console.ReadLine();


  30:   


  31:          }


  32:      }


  33:  }


Labels: , , , ,

3/5/08

RPG Variables vs C# Variables

In RPG we define variables in our 'D or C Specs.  We don't have to  uniquely declare character or numeric-  just the inclusion of a value in the decimal places column is enough. Leave it out and you just defined a character variable.
For the most part this is all you need to write 90% of business applications. There are other variable types such Binary, Graphic etc but these are encountered less often.
 

DName+++++++++++ETDsFrom+++To/L+++IDc.Keywords++

D NameofDog       S             24              
D Counter S 2 0
D Price S 5 2
D Datefield S D

Here's the equivalent in C#


String NameofDog;
int Counter;
decimal Price;
DateTime datefield;



The first thing that you will notice is that there is no length defined for the fields in C#. That's a great improvement over RPG where you usually explicitly declare length and end up in lots of trouble when a value gets chopped off when moved to a smaller field.

In C# there are way more value types than needed such as byte (for numbers 0-255), sbyte, short, long, float etc.





Common Value Types in C#


Int - integer - whole numbers (no decimals). Useful for counting.


string - holds alphanumeric values


bool - true or false (similar to indicators)


double any decimal up to 15 significant digits


decimal - any decimal up to 28 sig. digits



The variable declarations in RPG did not quite translate to C#. There is no Date value type in C#.  The statement ' DateTime datefield;' declares an object reference called datefield. How do I know this? Only because I know there is not value type of date in C#.  The fact that I am declaring an object called datefield just as I would a variable value brings up all sorts of interesting things about C# - mainly that objects are just another kind of variable. More on that later.



What about Operations on variables?


Let's add 1 to Counter in RPG and C#



RPG



Counter = Counter + 1;


C#


Counter = Counter + 1;



The code is the exact same in both!  There are other differences but we'll get operations in another post.




Lot's of free stuff inside


When you declare a variable in C# whether it is a value type like an integer or a 'reference' type like the DateTime object I created, along with the variable comes packaged  actions you might need on it.  In RPG if I want to convert my counter to a string variable, I would do the following.





RPG


Character = %char(Numeric); 



In C#, there is a method or function included in the variable when you declare it. The brackets indicate that ToString is a method.



Character = Numeric.ToString();



This is a fundamental and important aspect of C# - The actions you perform on variables and objects are often methods of that variable or object. If you want to trim the end of a string in C# you just say Character.Trim(); . Because you declared Character as a type String and String has all these methods now Character has them. There is no 'trim' opcode or expression. It's a method of string and when you declare a variable as a type string it gets all the methods belonging to string.

What's great about this is that you don't have to wait 10 years for IBM to come up with another op-code - you just write one yourself!  But, you may be asking, how do I know what method to use? There must be thousands. There are. However the Visual Studio IDE makes it simple and has a feature called intellisense - it fills out the statement as you type showing a drop down of all the methods and properties of an object or variable. Don't worry if this doesn't make a huge amount of sense right now. You'll get the hang of it with practice but it is one of those kind of mind-flips that is a big switch from Procedural RPG and Object Oriented C#.  It also makes sense. While RPG is an awesome language it has hit a stone wall. Creating lots of more opcodes or expressions is just going to make the language more complex. C# doesn't need lots of 'op-codes' - in fact there are about 77 in C# 2.0 and many you will never use. Most actions come from methods in classes.

Labels: , , , ,