Click here to Skip to main content
Click here to Skip to main content

Persisted Data in C#

, 17 Feb 2005
Rate this:
Please Sign up or sign in to vote.
This article builds a persisted data application in C#.

Introduction

I have built a Persisted data program for the Amateur Radio community. The reason I chose Amateur Radio is because it is something I live with on a day to day basis. I can therefore use the program everyday, and edit the code as and when necessary. This particular program is directed towards Amateur Radio contesting. This is an event in which each participating station tries to make as many radio contacts as possible, within a limited amount of time. The rules are complicated and are beyond the scope of this article. This therefore is a "bare bones program", and is not necessarily a finished product. The data is formatted in "Cabrillo format" which is specified by the Amateur Radio Relay League. There are several Cabrillo format styles, so this program could have reusable classes and methods to support several Windows Forms. This article merely serves to demonstrate Persisted data.

Persisted data

Persisted data is the backbone of the computer industry, and is used in every aspect of the computing world. Scientific communities, banking, government, and commerce all use Persisted data. This is what made IBM what it is today with its mainframe computing. .NET makes it possible to adapt mainframe technology to the modern PC.

Data is written to an external file, in this case, with a .dab suffix. All files written by this program will use the user created suffix. This program will open no other files, and all files created by this program will be proprietary. I have included a test file Test1.dab for your convenience. There is no internal data in the program, so upon starting the program you must either create your own file, or open the test file provided. When you create a file you will be prompted to restart the program.

When .NET was introduced in 2002, a new era of Persisted data began for the .NET community. Prior versions of this platform, such as VB-6 used the msFileCreate method, and created a text file with "end of line" characters as the only division between records. Version 7.0 of .NET introduced "field" structure, so that not only could data be retrieved by a record index number, fields could also be identified by name. Therefore, arrays could have a horizontal structure, in that they could contain a record, or a vertical structure in that every field could be written to a different array. This is useful for full text searches where records have met the search criteria. An intCounter variable can be incremented, and can tell us how many records that meet the search requirements have been returned.

This program presents "double click editing." Once a file has been opened, double click on a record, and it will split the fields into the appropriate textboxes for editing. The user can then make necessary changes, and press "Enter" to write them to file. There is no "delete record" function in this program, as this would destroy the sequential record index numbering, and would therefore corrupt the file. Entering a record is easy, and after entering the first record, useful fields are given default values, and subsequent records are easier, and faster to enter using the "Enter" key. In .NET, events are owned by the control, so in this particular program, records can only be entered from the last "Comment" textbox, when that control receives "focus." By using reusable subroutines, this capability can be expanded. There is no point in this article to include a lot of repetitious events. Enter a Callsign that you see on the screen in Received Callsign, and a full text Callsign search is made, returning the matching records in the lower textbox. At least one record must have first been written to the file before the Callsign search is unlocked. Boolean variables make excellent conditionals for locking, or unlocking program features. I have utilized reusable subroutines to allow the editing of any field in the record from any textbox.

Sample code

private void miOpen_Click(object sender, System.EventArgs e)
{
    AddRecOpen = true;
    // Disable menu items
    miOpen.Enabled = false;
    miNew.Enabled = false;
                
    // Start backgound thread for ProgressBar
    if( timedProgress.ThreadState.ToString() == "Unstarted")
    {
        timedProgress.Start();
    }
                        
    // Configure progbar
    progbar.Minimum = 1;
    progbar.Maximum = 1000;
    progbar.Step = 1;
    
    //'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
    //Open fileInput, Iterate thru file, print to txtBox, set txtNumber to 
    //last record number'
    //'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
                
    // Set Filters
    fileChooser.Filter = "Davco File (*.dab)|*.dab";
    fileChooser.FilterIndex = 1;
                
    // create dialog box enabling user to open file
    DialogResult result = fileChooser.ShowDialog();
                
    // get file name from user
    fileName = fileChooser.FileName;
                
    // exit eventhandler if user clicked Cancel
    if ( result == DialogResult.Cancel )
        return;
    
    // show error if user specified invalid file
    if ( fileName == "" || fileName == null )
        MessageBox.Show( "Invalid File Name", "Error",
        MessageBoxButtons.OK, MessageBoxIcon.Error );
    else
    {
                    
    fileInput = new FileStream( fileName, 
    FileMode.Open, FileAccess.Read );
                
    // use FileStream for BinaryWriter to read bytes from file
    binaryInput = new BinaryReader( fileInput );
                    
    // Calls and writes information function to txtRoot.Text
    txtRoot.Text = information(); 
                    
    currentRecordIndex = 0;
    }
                
    for(int i = 0; i < 1000; i++)
    {
        Record record = new Record();
                 
        // read record and store data in TextBoxes
            try
            {
            // get next record available in file
            while( record.Number == 0 )
                        {
            //Reset progressBar to start if required
            if (progbar.Value == progbar.Maximum) 
            {
                progbar.Value = progbar.Minimum ;
            }
            else 
            {
                progbar.PerformStep();
            }
                            
            // set file position pointer to next record in file
            fileInput.Seek( 
            currentRecordIndex * Record.SIZE, 0 );
                            
            currentRecordIndex += 1;
                            
            // read data from record
            record.Number = binaryInput.ReadInt32();
            record.Frequency= binaryInput.ReadString();
            record.Mode = binaryInput.ReadString();
            record.Date = binaryInput.ReadString();
            record.Time = binaryInput.ReadString();
            record.SntCallsign = binaryInput.ReadString();
            record.SntRst= binaryInput.ReadString();
            record.SntXchg = binaryInput.ReadString();
            record.RecCallsign = binaryInput.ReadString();
            record.RecRst = binaryInput.ReadString();
            record.RecXchg = binaryInput.ReadString();
            record.Comment = binaryInput.ReadString();
    
            }
                        
            // store record values in temporary string array
                string[] values =  { 
                       record.Number.ToString(),
                           record.Frequency,
                       record.Mode,
                       record.Date,
                       record.Time,
                       record.SntCallsign,
                       record.SntRst,
                       record.SntXchg,
                       record.RecCallsign,
                       record.RecRst,
                       record.RecXchg,
                       record.Comment
                       };
                       
          // copy string array values to txtView values
          SetTextBoxValues( values );
          stringValues = "QSO: {1, 5} {2, -3}{3, -11}{4, -5}" +
          "{5, -14}{6, -4}{7, -7}{8, -14}{9, -4}{10, -7}{11, -1}   \r\n";
          Sb.AppendFormat( stringValues, values );
          lstRecord.Items.Add(Sb.ToString());
          txtView.AppendText(Sb.ToString());            
          // Erase stringBuilder
          Sb.Remove(0, 86);
                        
          // if work offline is set then set focus to txtTime.Text
          if(timer1.Enabled == false)
          {
              txtFrequency.TabStop = false;
              txtMode.TabStop = false;
              txtDate.TabStop = false;
              txtTime.TabStop = false;
              txtSntCallsign.TabStop = false;
              txtSntRst.TabStop = false;
              txtRecRst.TabStop = false;
              // Shift focus to txtFrequency
              txtFrequency.Focus();
          }
          else
          {
              // if working online set focus to cmboCallsign.Text
              txtRecCallsign.Focus();
          }
    }
          // handle exception when no records in file
          catch( IOException )
          {
          ClearTextBoxes();
          // break out of loop; it is within sight so don't sweat it
          goto Breakout;
          }
          finally
          {
          // increment last record number by 1
          count += 1;
          txtNumber.Text = count.ToString();
         }
    }
                
          Breakout:
          // close streams if no records in file
          fileInput.Close();
          binaryInput.Close();
          txtRecCallsign.Focus();
          timer1.Enabled = true;  
                    
          // show error if user specified invalid file
          if ( fileName == "" || fileName == null )
          MessageBox.Show("Invalid File Name", "Error",
          MessageBoxButtons.OK, MessageBoxIcon.Error);
          else
          {
          // open file if file already exists
          try
          {
               //create FileStream (ReadWrite) to hold records
               fileOutput = new FileStream( fileName, 
               FileMode.OpenOrCreate, FileAccess.ReadWrite );
    
               // create object for writing bytes to file
               binaryOutput = new BinaryWriter( fileOutput );
               binaryInput = new BinaryReader( fileOutput );
                        
               timer1.Enabled = true;
               runOnce += 1;
                        
               // Updates information to txtRoot.Text
               txtRoot.Text = information(); 
               txtRecCallsign.Text = "";
               txtRecXchg.Text = "";
               txtComment.Text = "";
          }        
          finally
          {
               // snap lstView to last record
               if(  Int32.Parse(txtNumber.Text) > 16 )
               this .lstRecord.SetSelected((count - 2), true);
               // Initializes txtBoxes
               // Set TabStops
               Reset();
               progbar.Visible = true;
                    
               // Stop Progress Bar Thread
               timedProgress.Abort();
                        
          }
       }
}

Summary

Build your own program with the functions that you would like to use. I use many text searches in mine to give me information about radio propagation. I have also incorporated charts in my program at home here to show useful information such as "Number of contacts per month" in any given year, or "Number of contacts on each Band" in any given year. You might include a chart that shows "Number of contacts per hour." There are many more Cabrillo formats available for other contests, or we might decide that we like our own formatting better.

You have the ability to build a project that suits your own taste.

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here

Share

About the Author

Dave Brighton
Web Developer
United States United States
I studied Fortran IV in HighSchool where we had 2 keypunch machines, and access to an IBM 1100 at the Community College. We ran our programs batch, and compiled our programs on paper tape.
 
Years later when PC's became affordable, I gave programming another shot. This time I studied RPG with the IBM AS-400 computer. I could access the College Computer with Emulator Software( Mocha Soft MW 5250 ) and my home PC.
 
C++ came later, then VB-6, C#.Net, and Managed C++. I am currently studying VB.Net

Comments and Discussions

 
GeneralMy vote of 5 Pinmembermanoj kumar choubey26-Feb-12 22:37 
GeneralRegex for Amateur Radio Callsign PinmemberMike7323-Feb-07 10:37 
GeneralRPGIV PinmemberJohn H Long22-Mar-05 10:19 
QuestionCan you explain to me why is this? PinmemberTesic Goran22-Feb-05 9:32 
AnswerRe: Can you explain to me why is this? PinmemberDave Brighton24-Feb-05 12:30 
QuestionHave you Checked out Db4o? PinmemberAggieBioCoder26-Jan-05 6:51 
AnswerRe: Have you Checked out Db4o? PinmemberDave Brighton27-Jan-05 10:07 
AnswerRe: Have you Checked out Db4o? PinmemberGary Thom31-Jan-05 10:04 
GeneralThreading PinmemberGary Thom25-Jan-05 13:05 
GeneralImage Size PinmemberGary Thom25-Jan-05 12:57 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.

| Advertise | Privacy | Terms of Use | Mobile
Web03 | 2.8.141216.1 | Last Updated 17 Feb 2005
Article Copyright 2005 by Dave Brighton
Everything else Copyright © CodeProject, 1999-2014
Layout: fixed | fluid