Framework Dependency & Software Deployment Issues

I love Microsoft.  Simply because a big part of my career relies on their products and they have products that make my job a little bit easier. But sometimes they piss me off. There, I said it.

When are we ever going to catch a breath? I mean with the speed they are releasing stuff, it’s hard to keep up. And it’s hard to stick to one product, because I agree that the new products they release make it easier to write software, but you need time to learn and get comfortable with the new versions, and by the time you are comfortable and ready to do the magic, KA-BOOM!! There is a newer version 4.x

42-15251289

My problem with this issue specifically is that I think MS if forgetting those of us in the growing market. I mean let’s take the .Net framework for example. Vista ships with .Net Framework 3. With my country, Tanzania as an example, very few people/companies are using Windows Vista. Most of the users there are still on windows 2000 with some of them using windows XP.

The Internet Speed Problem.

The internet here in Africa is still an issue. The speeds are very low and very few can afford speeds of up to 1.0 Gbps. Which cost a fortune by the way. I’d say 90 percent are in the ranges or 400 – 1024 KBps. So you’ll understand when I say it’s a pain for someone to download a 20MB file. So when I write an application based on the .Net Framework 2.0, I’d have to download the runtime setup file, and find some means of getting that to the client and installing it on every machine that’s going to use the application, before I install my 2MB application. Talk about pain.

Deployment Issues.

Now I’d like to say that the .Net Framework 3.5 makes it real easy to write data access or all kinds of applications, with the release of LINQ and other stuff in this version. Writing applications has been simplified a lot, and I love this framework and would love to write all my applications using this version. But now I am still forced to use the old framework 2.0 because of the smaller size of the runtime installer.

The problem is this. The .Net framework 3.5 runtime installer is 200MB. That is TWO HUNDRED megabytes. If I write and application based on the framework, say my application is 5MB. I’ll have to download, and install the 200 MB runtime version on every client machine that’s going to use my 5MB application.

Say I wanted to send my application installer by email to a client who’s like in another country. The prerequisite in order for the application to run on the user machine will be the 200MB .Net Farmework runtime. With a internet speed of 250Kbps, do you know how long it’s going to take to download the installer? 2 years that’s how long it’s going to take.

42-15251289

For a user, or anyone really, this doesn’t make sense. Why didn’t MS create a smaller runtime version which could be like 30 MB or something in that range, that can be downloaded in a day or two with our slow 20Kbps connections??

Scott Hanselman has a website here which is supposed to read your machine and advise you on the smallest framework to download or something like that.  If you do not have any version of the framework on your machine though, it’s still 200MB for you to download.

We can’t resist innovation and forward movement in terms of software development and tools that make the process a little less painful. What we are asking is for the big software vendors to think about us and make it a little easier for us to distribute the software as well. Otherwise it’ll be just hard to adopt to the new changes if they make it even harder for us to distribute our work.

An Overview of Processes and Threads in .Net

It’s been a while since I last posted. I had been tied to projects and couldn’t escape to update the blog. But now I am back and ready to roll.

Today I’ll define the differences between a Process and a Thread. First things first, let’s see the definitions.

A process:

Simply put a process is a term used to describe the set of resources (such as external code libraries and the primary thread) and the necessary memory allocations used by a running application.

For each .exe loaded into memory, the OS creates a separate and isolated process for use during it lifetime. Using this approach to application isolation, the result is a much more robust and stable runtime environment, given that the failure of one process does not affect the functioning of another.

Every win32 process is assigned a unique process identifier (PID).

A Thread:

A thread can simply be defined as a path of execution within a process. The first thread created by a process’s entry point is called the primary thread.

Every Win32 process has exactly one main thread that functions as the entry point for the application. A Win32 Graphical User Interface (GUI) application defines a method called WinMain() as the application entry point, while a console based application defines the Main() method as the entry point.

process-thread relationship

The .Net Framework provides the System.Diagnostics namespace that offers, among others, some types that help with the interaction and manipulation of processes programmatically.

This code below for example will enumerate and list all the running processes and all the active threads running under each process.

I will not go into the details of explaining all the keywords in the code at this moment, but this is simply to further elaborate the differences between a Process and a Thread.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
//for processes
using System.Diagnostics;

namespace ThreadvsProcess
{
class Program
{
static void Main(string[] args)
{
Console.WriteLine("xxxxx Processes and Threads in .Net xxxxx\n");

ShowRunningProcesses();

//press Enter to exit
Console.ReadLine();
}

static void ShowRunningProcesses()
{
// List all the processes currently running on the local machine.
Process[] allProcesses = Process.GetProcesses(".");

// Show the Process ID (PID) and name of each process.
foreach (Process p in allProcesses)
{
string details = string.Format(" Process ID: {0}\tName: {1}",
p.Id, p.ProcessName);
Console.WriteLine(details);
//show the Threads running under this process
DisplayThreadsForPID(p.Id);
}
Console.WriteLine("xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx\n");
}

static void DisplayThreadsForPID(int pID)
{
try
{
Process currProc = null;
currProc = Process.GetProcessById(pID);

// List out the details for each thread in the specified process.
Console.WriteLine(" Threads used by: {0}",
currProc.ProcessName);
ProcessThreadCollection allThreads = currProc.Threads;
foreach (ProcessThread th in allThreads)
{
string detail =
string.Format(" Thread ID: {0}\tTime Started: {1}\tPriority: {2}",
th.Id, th.StartTime.ToShortTimeString(), th.PriorityLevel);
Console.WriteLine(detail);
}
Console.WriteLine("xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx\n");
}
catch (Exception)
{
//ignore the exception for simplicity
return;
}
}

}
}

If you run this code, you’ll see the output similar to the one shown in the  image below depending on the processes currently running on your machine.

output

There’s a lot more you can do with Processes and Threads apart from just enumerating and dumping them to the console window and this was just a scratch at the top to show the differences between the two.

Till next time, yours truly.

Sorting by IComparable vs IComparer

These are two interfaces that used to confuse me. I didn’t know when to use one or when to use the other. The aim of this post is to make it easier for someone to understand the differences and choose appropriately.

In as a few words as possible:
i)A class that implements IComparable can be sorted or compared to another class instance in a manner that you define.

ii)A class that implements IComparer can be used to sort or compare classes that do or do not implement IComparable.

The List.Sort() Method.

Every list(generic list, array, arraylist) has a built-in method called Sort(). The Sort() method knows how to sort all objects that implement the IComparable interface. The method uses an object’s CompareTo() method to compare it with other objects and use its return value to figure out which object comes first.

To sort objects that do not implement IComparable, you have the IComparer Interface. It’s used to assist the list’s Sort() method in sorting its members.

IComparable.
You implement this within the class you want to be sorted. The interface has only one method called CompareTo() that takes an object as a parameter, compares it with the class and returns an integer value that figures out which object comes first.

See the sample class below.

Public Class Person
    Implements IComparable(Of Person)
    'these should be properties
    Public FirstName As String
    Public LastName As String
    Public Age As Integer

    Public Sub New(ByVal first As String, ByVal last As String, ByVal age As Integer)
        Me.FirstName = first
        Me.LastName = last
        Me.Age = age
    End Sub

    Public Function fullName() As String
        Return Me.FirstName & " " & Me.LastName & ": Age - " & Me.Age
    End Function

    Public Function CompareTo(ByVal other As Person) As Integer Implements System.IComparable(Of Person).CompareTo
        If Me.Age > other.Age Then
            Return 1
        ElseIf Me.Age < other.Age Then
            Return -1
        Else
            Return 0
        End If
    End Function
End Class

Notice the CompareTo() method. It takes another Person class as a parameter, compares the Ages and returns a number indicating
which one comes first. In this method you can create any sorting logic that you need.
You could for example compare by Age, FirstName or Lastname. In this sample the classes will be sorted by Age.

Implementation:
One you have a list of objects that implement IComparable, all you have to do to sort them is just call the List.Sort() method without
passing any parameters. See sample code for a button bellow.

Dim list As List(Of Person)

    Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
        list = New List(Of Person)
        list.Add(New Person("Nick", "Masao", 27))
        list.Add(New Person("Sydney", "Mtaita", 3))
        list.Add(New Person("Ruth", "Mtaita", 23))

        Debug.WriteLine("")
        Debug.WriteLine("Unsorted:")
        For Each p As Person In list
            Debug.WriteLine(p.fullName)
        Next

'Just call the sort method without passing any parameters and you are done
‘The Sort() method uses the logic in the CompareTo() method in the class to ‘sort the list members

        list.Sort()

        Debug.WriteLine("")
        Debug.WriteLine("Sorted by Age:")
        For Each p As Person In list
            Debug.WriteLine(p.fullName)
        Next
End Sub

The code produces the following output.
IComparable_Output
As you can see the objects were sorted by age.

IComparer.

Implement this in a class that you will use to sort other classes that may or may not implement IComparable. This class will be a ‘comparer’ and will impose the sorting order in the List.Sort() method. The interface has only one method called Compare() that takes two objects and returns a value which determines which object comes first.

To sort a list using IComparer, you need to create a new instance of the class that implements it and pass that instance to the List.Sort() method. The list object will then use the class’s Compare() method to sort the members.

Say for example you have a person class with the following definition.  Note that it doesn’t implement any interface.

Public Class Person
    'these should be properties
    Public FirstName As String
    Public LastName As String
    Public Age As Integer

    Public Sub New(ByVal first As String, ByVal last As String, ByVal age As Integer)
        Me.FirstName = first
        Me.LastName = last
        Me.Age = age
    End Sub

    Public Function fullName() As String
        Return Me.FirstName & " " & Me.LastName & ": Age - " & Me.Age
    End Function
End Class

Now to use IComparer to sort a list of objects like the above, you need to create a simple class that implements IComparer and define the sorting manner, like so.

Public Class PersonComparer_ByAge
    Implements IComparer(Of Person)

    Public Function Compare(ByVal x As Person, ByVal y As Person) As Integer Implements System.Collections.Generic.IComparer(Of Person).Compare
        If x.Age > y.Age Then
            Return 1
        ElseIf x.Age < y.Age Then
            Return -1
        Else
            Return 0
        End If
    End Function
End Class

The Class sorts the Person objects by Age. You could also sort by FirstName or LastName. The only limitation of
IComparer is that it has access to public members of the class only.

See another class that implements IComparer but this time sorts by the FirstName field.

Public Class PersonComparer_ByFistName
    Implements IComparer(Of Person)

    Public Function Compare(ByVal x As Person, ByVal y As Person) As Integer Implements System.Collections.Generic.IComparer(Of Person).Compare
        If x.FirstName > y.FirstName Then
            Return 1
        ElseIf x.FirstName < y.FirstName Then
            Return -1
        Else
            Return 0
        End If
    End Function
End Class

Implementation:
If you have a list of objects, and you have a class that implements IComparer and has the sorting criteria like
the above class then you have to do the following to sort your list.

  1. Create an instance of your sorting class.
  2. Pass that instance to the list.sort() method.
  3. That’s it.

Sample button code that implements the code above.

Private Sub Button2_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button2.Click
        list = New List(Of Person)
        list.Add(New Person("Nick", "Masao", 27))
        list.Add(New Person("Sydney", "Mtaita", 3))
        list.Add(New Person("Ruth", "Mtaita", 23))

        Debug.WriteLine("Unsorted:")
        For Each p As Person In list
            Debug.WriteLine(p.fullName)
        Next

        Debug.WriteLine("")

'instantiate the sorter/comparer class that implements IComparer

        Dim sortName As New PersonComparer_ByFistName

'pass it as criteria to the sort method

        list.Sort(sortName)

        Debug.WriteLine("Sorted by Firstname:")
        For Each p As Person In list
            Debug.WriteLine(p.fullName)
        Next

        Debug.WriteLine("")
'instantiate the comparer class and pass it to the sort method
        Dim sortAge As New PersonComparer_ByAge
        list.Sort(sortAge)

        Debug.WriteLine("Sorted by Age:")
        For Each p As Person In list
            Debug.WriteLine(p.fullName)
        Next
    End Sub

The above code produces the following output.

IComparer_Output

Advantages & Limitations.

The advantage of IComparable is that you have access to the private members. i.e you can create your sorting criteria using private members in the class since the CompareTo() method is withing the class. The limitation is you only have that one way of sorting.

The limitation of IComparer is that the object that implements it doesn’t have access to private members of the objects it sorts. It only has access to public members.

Its advantages are, as seen in the sample code above, you can create a number of sorting options, and you have the option of passing the more specific and more appropriate sorting criteria to the Sort() method.

This post is getting too long  and I think I’ll end it here. Hopefully it was an eye opened of some sorts. Till next time, yours truly.

Bug caused by not paying attention.

I recently wrote the function below in MS Access VBA. I have a string that represent a year formatted as yyyy/yy and the function should return the string as yyyy-yyyy. It makes use of the Access Mid function that gets a substring of a text from any position. So here’s the function.

'returns the year in format 2010-2011
Public Function FormatYear(ByVal theYear As String) As String
On Error GoTo errHandler

Dim first, last, result As String

    first = Mid(theYear, 1, 4)
    last = Mid(theYear, 6, 2)
    result = first & "-20" & last

    FormatYear = result

exitHere:
 Exit Function

errHandler:
 MsgBox err.Description
 Resume exitHere

End Function

So I called the function as shown below and got the weird results. Can you spot the not??

debugWindow

Yeah. The problem was that I supplied the year to the function as a string but without the quotation marks.  Like 2010/11 instead of  “2010/11″ . And that was the cause of the weird results. I guess I was tired.

So after a cup of coffee and a 10 minute break I realized the bug and as you can see below, voila.

debugWindowCorrect

So please pay attention or take a break if you feel like your concentration level is going down.

Till next time, yours truly.

Tips from the field for Software Developers

Hello everyone, my name is Nick and I’m a software developer. I wanna give you guys some tips on the software development process based on a little experience from the front line.

The classic image below(courtesy of http://i.techrepublic.com.com) tells most of the story.

software-engineering-explained

Project Requirements:

  • Make sure you have all the information you need from the client before you write a single line of code.
  • Make sure the client knows what they need and they have given you all the information you need before you write one line of code.
  • Write a spec and make sure you share it with the client and have them confirm that it is exactly what they need. (If possible write the spec together.)
  • Repeat until everything is 100%  clear of what they want to see in the final product.

The point of the above list is that it’ll help you to avoid some issues like you are 98% into the development, finalizing and ready to deliver and the client will come up with something they missed that they need you to add to the application and you’ll have to break down 3 quarters of the app to apply this new feature.  And I have to tell you its not going to be easy.

Finally, make sure you update the clients on your development and if possible make sure they test the product throughout the process to avoid big surprises in design change decisions.

That’s all I have for now, till next time. Yours truly.

Create a Visual Basic Dynamic-Link Library(dll) from the command line.

A Dynamic-Link Library is a non executable program made of one or more files, which contains classes, procedures, and/or other resources that other programs can use.  Because it is not an executable, it doesn’t need an entry point or the main() procedure  and it usually ends with .dll

Well, you can read more about Dynamic link libraries(dlls) on msdn or wikipedia.

In this post I’ll show you how to create a VB.Net DLL from the command line.

First you need to set up your system to use the vbc compiler. If you do not know how to do this, please read my previous post here.  So from now on I’ll assume you have set up your compiler and we are ready to go.

Steps:

  • Open notepad,  create a class, call it Person and save it as a VB file (Person.vb) . For this post we’ll create a simple Person class.  See the code for the class at the end of the post below.

>>CodeListing No.1 – The Person Class

  • Create a new folder in your main drive (in my case C:\) and call it PersonLibrary.  Save the above class in this folder.
  • Click Start > Run > type cmd  and click OK to open the command prompt.
  • Change to the PersonLibrary directory as shown in the image below.

changedirectory

How to Create a Dynamic-Link Library from the command line.

  1. There are two options. The first one is you create a library that has the same name as the source file.
  • To create a Dll that has the same name as the source file, at the command prompt type the following command.

vbc /target:library Person.vb

  • The command is vbc /target:library nameOfSourceFile.vb notice the space after vbc and the other space after library. Make sure you include them.
  • Browse to the PersonLibrary folder and you’ll see that the Person.dll dynamic-link library has been created. See the image below.

personlibrary1

2.  The other option is that you can provide your own name for the library.

  • To create a Dll that has your own desired name, at the command prompt type the following command.

vbc /target:library /out:PersonLibrary.dll Person.vb

  • The command is vbc /target:library /out:DesiredNameOfLibrary.dll nameOfSourceFile.vb
  • Now browse to the PersonLibrary folder and you’ll see the newly created dll with our custom name PersonLibrary.dll, as well as the old one, Person.dll

personlibrary2

And thats all there is to it. You are done and you have your libraries and you can distribute them now or use them from an application.

How to use the Library.

Before you use the library you simply have to import it into your project and add it as a reference using the command line when compiling.

  • Open Notepad and type in the following code
Imports System
Imports PersonLibrary

Module MainModule
    Sub Main()
        Dim p As New Person("Mike F", "Masao")
        p.Addresses(0) = "6032, Olacity, Arusha"
        p.Addresses(1) = "Tanzania"
        p.Citizenship = "Tanzanian"
        p.BirthDate = #8/21/1982#

        Console.WriteLine("Full Name: " & p.FullName("Mr."))
        Console.WriteLine("Address1: " & p.Addresses(0))
        Console.WriteLine("Address2: " & p.Addresses(1))
        Console.WriteLine("Citizenship: " & p.Citizenship)
        Console.WriteLine("Age: " & p.Age)

        Console.Read()
    End Sub

End Module
  • Save the file as MainProgram.vb under our PersonLibrary folder.
  • Now go back to the command prompt and issue the following command, which will add the library as a reference to the project and then compile the MainProgram code to an executable.

vbc /reference:PersonLibrary.dll MainProgram.vb

  • The command is vbc /reference:NameOfLibrary.dll NameOfMainProgram.vb
  • After the above steps, browse again to the PersonLibrary folder and you’ll see your libraries and your MainProgram.exe executable file as seen in the image below.

aftercompiling

  • Now double click the MainProgram.exe file and you should see the following output on your screen.

output

And we are done.

So now you can create your own libraries by using just notepad and the command prompt.

Hope this was helpful. Till next time, yours truly.

CodeListing No.1  – The Person Class

Public Class Person
    'Fields
    Public FirstName As String
    Public LastName As String
    Public m_BirthDate As Date
    'You can define up to 4 addresses for this person
    Public m_Addresses(3) As String
    Public Citizenship As String = ""

    Sub New(ByVal firstname As String, ByVal lastname As String)
        Me.FirstName = firstname
        Me.LastName = lastname
    End Sub
    Public Property BirthDate() As Date
        Get
            Return m_BirthDate
        End Get
        Set(ByVal value As Date)
            m_BirthDate = value
        End Set
    End Property

    Function FullName(Optional ByVal title As String = "") As String
        FullName = ""
        'use the title if provided
        If title <> "" Then FullName = title & " "
        'append first and last names
        FullName &= FirstName & " " & LastName
    End Function

    'Age is a ReadOnly property
    Public ReadOnly Property Age() As Integer
        Get
            Return Year(Now) - Year(m_BirthDate)
        End Get
    End Property

    Public Property Addresses(ByVal index As Integer) As String
        Get
            If index < 0 Or index > UBound(m_Addresses) Then
                Throw New IndexOutOfRangeException("Invalid address Index")
            End If
            Return m_Addresses(index)
        End Get
        Set(ByVal value As String)
            If index < 0 Or index > UBound(m_Addresses) Then
                Throw New IndexOutOfRangeException("Invalid address Index")
            End If
            m_Addresses(index) = value
        End Set
    End Property

End Class

Using the Timer object and Event Handlers to automatically control actions.

I know I haven’t been able to write for a long time now, and I’ll still be lagging up, but hopefully soon I’ll be back, with full speed, bringing you a new post every week.

Today I’ll show you how to use the System.Windows.Forms.Timer to control when to perform some action or call some procedures. A good example is when you maybe need to send a report to your boss,  say every day at 4pm.timers

In this case, you need a timer object, that calls an event handler which checks the time against your system time to see if it is 4pm or after and then call the procedure that sends the report. Let’s see how you can go about, doing that.

What we need.

  1. A Timer object.
  2. A method to serve as an event handler
  3. Your custom method that does whatever work you want done when it’s time.

We’ll make use of the AddHandler statement to hook up the Timer’s Tick event with our event handler. The AddHandler statement is used to associate an event with an event handler at run time.

See the full code below.

Imports System

Module Sample

Public Class Test

Private Shared myTimer As New System.Windows.Forms.Timer()

Public Shared Sub Main

	'hook up the event to the handler method

        AddHandler myTimer.Tick, AddressOf CheckTime

        ' Sets the timer interval to 1 second and start it.

        myTimer.Interval = 1000

        myTimer.Start()

	MsgBox("The timer is running now....")

	Console.Read()
   RemoveHandler myTimer.Tick, AddressOf CheckTime

End Sub

Public Shared Sub CheckTime(ByVal sender As System.Object, ByVal e As System.EventArgs)

        If DateTime.Parse(DateTime.Now.ToShortTimeString) > DateTime.Parse("11:00 AM") Then

            MsgBox("The time is : " & DateTime.Now.ToShortTimeString)

            'Call SendPendingInvoices()

        End If

    End Sub

End Class
End Module

As you can see above, we created a new Timer object, and in our main procedure, or start up procedure, we hooked up the Timer.Tick event to our CheckTime event handler method, so that it gets called every time the tick event of the timer is fired.  In our case that will be every 1 second.

To test the code, create a new blank console project and copy and paste the code above and simply click run. If your system time is greater than 11:00 AM then you should see a message box pop up every second showing you the current time from your system.

Hope this was helpful.

Till next time, yours truly.

A method for searching a ListView

Here is a simple method that will search a ListView and its subitems and select or highlight the ListViewItem or SubItem that begins with  the search criteria.

In this sample I make use of the ListView.FindItemWithText method which takes three parameters, the first a string specifying the item to find, second a boolen value to specify whether the subitems should be included and the third, the starting index in the listview items collection.

This is how the method works.

  1. The method takes two parameters, first the name of the ListView, and second the text to find.
  2. It starts the search at the first item and goes on until it finds a match. The found ListViewItem is then highlighted.
  3. If you click search again, its starts at the index of the last item and continues until it finds another match.
  4. If no match is found and you click search again, it starts from the beggining, at the first item’s index.

Using the code.

Create a listview object, load it with items and subitems. On your form, outside the method, create these 2 variables:

  • lastSearch, String - This will save your previous search text and compare it with the current text when you call the method again.
  • lastIndex - Integer – Set it to -1. - This will save the index of the found item so that the method starts from here when called again.

After this, call the method and pass the name of the listview you want to search and the text to find.

Here is the full code. You can use it as is, or you can modify it and add some changes as you see fit.

    Private lastSearch As String = ""
    Private lastIndex As Integer = -1

Private Sub SearchListView(ByVal listView As ListView, ByVal txtFind As String)

        Dim foundItem As ListViewItem = Nothing

        If lastSearch = txtFind Then
            If lastIndex < listView.Items.Count - 1 Then
                foundItem = listView.FindItemWithText(txtFind, True, lastIndex + 1)
            Else
                foundItem = listView.FindItemWithText(txtFind, True, 0)
            End If
        Else
            foundItem = listView.FindItemWithText(txtFind, True, 0)
        End If
        lastSearch = txtFind
        lastIndex = -1
        If Not (foundItem Is Nothing) Then
            lastIndex = foundItem.Index
            listView.Focus()
            listView.Items(foundItem.Index).Selected = True
        End If
    End Sub

I wrote this in .Net 2.0 but it should work with 3.0 and 3.5. The method is not perfect, its just an eye opener and the rest is up to the user to dig and improvise.

Till next time, yours truly.

Parameters order in ADO.Net command objects.

I didn’t know that the order of parameters in a SQl statement mattered. At least when using MS Access as your back-end. Untill recently when I wrote the function below that updates an MS Access  2003 Database.

Public Function Update() As Integer
           Using cn As New OleDbConnection(ConnectionString)
            Dim sql As String = "UPDATE SupplyItem SET Balance = @Balance " & _
                                       "WHERE ProductID = @ProductID AND UnitID = @UnitID;"

            Dim cmd As OleDbCommand = New OleDbCommand
            cmd.Connection = cn
            cmd.CommandType = CommandType.Text
            cmd.CommandText = sql
            cmd.Parameters.AddWithValue("@UnitID", Me.UnitID)
            cmd.Parameters.AddWithValue("@Balance", Me.Balance)
            cmd.Parameters.AddWithValue("@ProductID", Me.ProductID)
            cn.Open()
            Dim res As Integer = cmd.ExecuteNonQuery
            cn.Close()
            Return res
        End Using

    End Function

I ran a unit test on the function and the test was failing. I tried again and again and it failed with some parameter error or something. I checked and rechecked the database, the parameters and everything. But it was still failing.

I got confused. You see, I thought that because the parameters are named, then it doesn’t matter in which order you suppply them to the command object. As long as you supply all the parameters and values, the query should work. Is it different for SQL server and for MS Access? or it doesn’t matter at all and maybe my system had other problems? I’m not sure.

So after a while and after trying everything else, I decided to change the order of the parameters to this.

            cmd.Parameters.AddWithValue("@Balance", Me.Balance)
            cmd.Parameters.AddWithValue("@ProductID", Me.ProductID)
            cmd.Parameters.AddWithValue("@UnitID", Me.UnitID)

And voila! It worked like magic. I was confused even more.

But I guess the more you write code, the more you discover little things that you overlooked before or didn’t bother to go into the details at an earlier time.

Till next time, yours truly.

Save and load Dataset Objects from XML

I love the .NET framework for the simplicity it has brought to application development in so many ways. Like in datacentric application development for example. You could save a whole dataset to disk with just one line of code. Thats right. 1 line.  And retrieve it again with just one other line.

In this post we’ll see a sample of how to do it.

So suppose you have this simple Student class.

Public Class Student
    Private first As String
    Private last As String
    Private _address As String
    Private _age As Integer
    Private _gender As String
    Private _Id As Integer

    Public Property ID() As Integer
        Get
            Return _Id
        End Get
        Set(ByVal value As Integer)
            _Id = value
        End Set
    End Property
    Public Property FirstName() As String
        Get
            Return first
        End Get
        Set(ByVal value As String)
            first = value
        End Set
    End Property

    Public Property LastName() As String
        Get
            Return last
        End Get
        Set(ByVal value As String)
            last = value
        End Set
    End Property

    Public Property Address() As String
        Get
            Return _address
        End Get
        Set(ByVal value As String)
            _address = value
        End Set
    End Property

    Public Property Age() As Integer
        Get
            Return _age
        End Get
        Set(ByVal value As Integer)
            _age = value
        End Set
    End Property

    Public Property Gender() As String
        Get
            Return _gender
        End Get
        Set(ByVal value As String)
            _gender = value
        End Set
    End Property

    Public Overrides Function ToString() As String
        Return FirstName & " " & LastName & ", " & Gender & ", " & Age & ", " & Address
    End Function
End Class

And let’s say you have this function that populates and returns a list of student objects.

Public Function GetPeople() As List(Of Student)
        Dim students As New List(Of Student)
        Dim one As New Student
        one.ID = 1
        one.FirstName = "Chan"
        one.LastName = "Dong"
        one.Gender = "Male"
        one.Age = Integer.Parse("26")
        one.Address = "Xin Xiao, China"
        students.Add(one)

        Dim two As New Student
        two.ID = 2
        two.FirstName = "Ruth"
        two.LastName = "Mtaita"
        two.Gender = "Female"
        two.Age = Integer.Parse("23")
        two.Address = "6032, Olasity, Arusha"
        students.Add(two)

        Dim three As New Student
        three.ID = 3
        three.FirstName = "Sydney"
        three.LastName = "Masao"
        three.Gender = "Female"
        three.Age = Integer.Parse("2")
        three.Address = "6032, Olasity, Arusha"
        students.Add(three)

        Dim four As New Student
        four.ID = 4
        four.FirstName = "Willy"
        four.LastName = "Masao"
        four.Gender = "Male"
        four.Age = Integer.Parse("24")
        four.Address = "Moshi, Tanzania"
        students.Add(four)

        Return students

    End Function

Now I’m going to create a dataset and a table, and fill the dataset with the students objects from above, save the dataset to disk as an xml file, modify the data in xml and then populate the dataset with the modified data from the xml file.

The method below creates the dataset and fills it with our students data.

Public StudentDataset As DataSet

    Public Sub FillDataset()
        StudentDataset = New DataSet
‘you need to make it perfect, add datatypes for the columns etc.
        Dim tb1 As New DataTable("People")
        Dim col1 As New DataColumn("ID")
        Dim col2 As New DataColumn("Firstname")
        Dim col3 As New DataColumn("Lastname")
        Dim col4 As New DataColumn("Gender")
        Dim col5 As New DataColumn("Age")
        Dim col6 As New DataColumn("Address")
        tb1.Columns.Add(col1)
        tb1.Columns.Add(col2)
        tb1.Columns.Add(col3)
        tb1.Columns.Add(col4)
        tb1.Columns.Add(col5)
        tb1.Columns.Add(col6)

        Dim row As DataRow = tb1.NewRow
        row(0) = GetPeople(0).ID
        row(1) = GetPeople(0).FirstName
        row(2) = GetPeople(0).LastName
        row(3) = GetPeople(0).Gender
        row(4) = GetPeople(0).Age
        row(5) = GetPeople(0).Address
        tb1.Rows.Add(row)

        Dim row1 As DataRow = tb1.NewRow
        row1(0) = GetPeople(1).ID
        row1(1) = GetPeople(1).FirstName
        row1(2) = GetPeople(1).LastName
        row1(3) = GetPeople(1).Gender
        row1(4) = GetPeople(1).Age
        row1(5) = GetPeople(1).Address
        tb1.Rows.Add(row1)

        Dim row2 As DataRow = tb1.NewRow
        row2(0) = GetPeople(2).ID
        row2(1) = GetPeople(2).FirstName
        row2(2) = GetPeople(2).LastName
        row2(3) = GetPeople(2).Gender
        row2(4) = GetPeople(2).Age
        row2(5) = GetPeople(2).Address
        tb1.Rows.Add(row2)

        Dim row3 As DataRow = tb1.NewRow
        row3(0) = GetPeople(3).ID
        row3(1) = GetPeople(3).FirstName
        row3(2) = GetPeople(3).LastName
        row3(3) = GetPeople(3).Gender
        row3(4) = GetPeople(3).Age
        row3(5) = GetPeople(3).Address
        tb1.Rows.Add(row3)

        StudentDataset.Tables.Add(tb1)
    End Sub

Now I’ll create a simple form, add a datagridview control in it. I’ll create a method within the form to save the dataset to XML, and then I’ll add another method to get the dataset from XML and fill the datagrid with the student records from our dataset.

Saving a Dataset to XML

This single line of code does that for us. The .Net method Dataset.WriteXml takes a file path and saves your whole dataset as an xml file. In this case, the path is the local application folder, and the file name is Studentdataset.xml

    Public Sub DatasetToXML()
        StudentDataset.WriteXml("StudentsDataset.xml")
    End Sub

See the dataset in Xml format below.
dataset_in_xml

Retrieving the Dataset from XML

Again notice the single line of code that retrieves the dataset from XML. The .Net method for the action is Dataset.ReadXml

Public Sub FillDatasetFromXML()
        Dim mydataset As New DataSet
'this line loads the dataset from Xml
        mydataset.ReadXml("StudentsDataset.xml")
'This code adds the records to the datagridview
        For Each row As DataRow In mydataset.Tables(0).Rows
            Dim i(5) As String
            i(0) = row(0)
            i(1) = row(1)
            i(2) = row(2)
            i(3) = row(3)
            i(4) = row(4)
            i(5) = row(5)
            DataGridView1.Rows.Add(i)
        Next

    End Sub

Now I’m going to open the xml file in notepad, or whichever xml editor that you may use, modify one record, save changes, and fill our datagrid with the modified dataset.

Here is the form loaded with data from the dataset that we retrieved from Xml.

gridview-initial

Edit the dataset in Xml

I’m changing all the details for the first student in xml format using notepad.

edit-with-notepad

After modifying the record and saving the changes, I go back to my form again and load the records from the modified Xml dataset. See the updated changes for the first student displayed in the form now.

updated-dataset

And here is the modified dataset in Xml view

modified

And here is the rest of the form’s code.

    Private Sub ButtonToXML_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles ButtonToXML.Click
        Call DatasetToXML()
    End Sub

    Private Sub ButtonFromXML_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles ButtonFromXML.Click
        DataGridView1.Rows.Clear()
        Call FillDatasetFromXML()
    End Sub

    Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
        Call FillDataset()
    End Sub

The dataset class has many other important methods you could use, for example in saving and retrieving table schemas etc. Its up to everyone to explore the powerful features and use them in their projects.

This was just a scrath at the top, on how you could save a dataset in xml, transfer it maybe over the network, and load it again on the other side ready for use.

Till next time, yours truly.

Next Page »


Need a .Net software developer to write your custom software?

Latest Tweets