Saturday, April 23, 2011

[ Dot Net Remoting ] - Using delegate for the Remote Functions in Both Sync, Async way


1. Introduction


In this article, I explain how will you use delegate on the functions exposed by the remote object. Also, I will explain how do we call those remote object functions in a synchronous way and in an asynchronous way. I do not want to explain threading here. But below is a very short note about Sync and Async function calls:

  1. The client function that makes a call to the remote function will wait for the completion of the remote function. This is a Synchronous call to the function exposed by the remote object.
  2. The client function that makes a call to the remote function will not wait for the completion of the remote function. This is Asynchronous call the function.

2. About the example


The Server in this example exposes a function that prints a running count taking some time. You can think of this function as long running task on the server. The function is just to simulate the long running process situation.

The client has two buttons and one function is calling the remote function in a synchronous way and other does the same in the Asynchronous way. The client uses the delegate of the same type to make a call to the remote functions.

When you click the Start Sync button, the count will be running on the server and once it is finished, the count on the form starts. The server shows the running count in the console window and client shows it in the text box. So, here the client will wait for the server completed the counts.

When you click the Start Async button, the count will run in parallel between a server and the calling client. That means, after the call the client will not wait for the server to complete its task. 

Fig 1. Example Application



3. Codes for The Server


The code for the server is similar to previous examples. So you will not see much explanation here repeated again. If you need much explanation on the server, please have a look at the First remoting article.

1) In the server, after creating the project a class called Counter is added and it is derived from MarshalByRef object. In the counter.cs file required namespace is included. This Counter class acts as the Remote class.

//RemSrv 01: Include required assemblies
using System.Runtime.Remoting;

2) The class has a constructor and a method PerformCount. This method will be called from the client using delegates. We will see about that in detail when we are moving to the client side coding. The code for this class is given below:

//RemSrv 02: Initialize the remoting object
public Counter()
{
    Console.WriteLine("Remote Object Created. " + Environment.NewLine);
}

//RemSrv 03: Perform the counting operation. This will take sometime and is useful to explain
//           How async call to this method is useful from the client end.
public void PerformCount()
{
    int x;

    for (x = 1; x < 10000; x++)
        Console.WriteLine("Current Count : " + x.ToString());

    Console.WriteLine("Counting is finished");
    return;
}

3) In the application entry, we are hosting the remote object under the name Counter. For more detail look at the basic article (the first one)

//RemSrv 04 : Required Assemblies
using System.Runtime;
using System.Runtime.Remoting;
using System.Runtime.Remoting.Channels;
using System.Runtime.Remoting.Channels.Tcp;

namespace RemotingDelegate
{
    class Program
    {
        static void Main(string[] args)
        {
            //RemSrv 05 : Create a communication channel (Server) and register it
            TcpServerChannel SrvrChnl = new TcpServerChannel(13340);
            ChannelServices.RegisterChannel(SrvrChnl, false);

            //RemSrv 06 : Register the Remote Class so that the Object can go
            //and sit on the Remote pool
            RemotingConfiguration.RegisterWellKnownServiceType(typeof(RemotingDelegate.Counter),
                "Counter", WellKnownObjectMode.SingleCall);

            //RemSrv 07 : Halt the server so that Remote client can access the object
            Console.WriteLine("Server is Running...");
            Console.WriteLine("Press Any key to halt the Server");
            Console.ReadKey();
        }
    }
}


4. Codes for The Client


The client is the windows application and the form details and what each UI is explained in section 2 of this article.

1) The below namespaces are included in the form to access the Remoting as well as very basic thread function Thread.Sleep. Also, note that the project reference for the server also included. Once the application is built properly then you can split the exes into server and client machines for testing purposes.

//Client 01: Include the required namespace
using System.Runtime.Remoting;
using System.Runtime.Remoting.Channels;
using System.Runtime.Remoting.Channels.Tcp;
using System.Threading;
using RemotingDelegate;

2) Once we are ready with the required namespaces, two delegates of the same are declared at the class level. Actually, one delegate is sufficient, I kept two just to differentiate the way I am going to use it.

//Client 03: Declare delegates for Sync Call and Async Call
public delegate void SyncCall();
public delegate void AsyncCall();

3) The LocalCounter function here does the same job of the function PerformCount on the server. So there are two long running tasks, one at the server side and the other one is at the client side.

//Client 06: Start the Local Counter. Assume that It is a long running task.
private void LocalCounter()
{
    long x;

    lblDisplay.Text = "Starting the Local Count...";

    for (x = 1; x < 10000; x++)
    {
        txtCount.Text = x.ToString();
        Application.DoEvents();
    }

   lblDisplay.Text = "Local Count is Done.";
}

4) The click event handler for the button Start Sync first creates the proxy for the remote object and stores that in the variable cntObj. Then a delegate object of type SyncCall is created and it is pointing the remote function PerformCount. The function PerformCount is passed to the delegate object by using the proxy cntObj. Once the delegate fnCounter is ready, a call to the remote function PerformCount is made using the delegate. And after that a call to the local task (LocalCounter) also made. Below is the code:

private void btnSync_Click(object sender, EventArgs e)
{
    //Client 02: Get the Proxy for remote object
    Counter cntObj = (Counter)Activator.GetObject(typeof(Counter),
        "tcp://localhost:13340/Counter");

    //Client 04: Call the remote method through the delegate. This call is Synchronous.
    SyncCall fnCounter = new SyncCall(cntObj.PerformCount);
    fnCounter();

    //Client 05: Call the Local Counter
    LocalCounter();
}

Note that after making a call to the remote object (by the statement fnCounter), the execution will pause till the remote function finishes its task. Once the task is completed on the server, the execution resumes here on the client and the function LocalCounter starts executing. You can observe this by running the sample, the count on the server is displayed in the console window, once the count is completed, you will see an increment in the counter on the textbox of the form.

5) For making the asynchronous call, the delegate is created is in the same way as we did in the previous step. Below is the code:

//Client 07: Create the proxy for remote Object and set the delegate to the required
//           remote function.
Counter cntObj = (Counter)Activator.GetObject(typeof(Counter), "tcp://localhost:13340/Counter");
AsyncCall FnCounter = new AsyncCall(cntObj.PerformCount);

6) Once the delegate is created, instead of directly calling the function, we are using the BeginInvoke method on the delegate. The first parameter is actually a call back that a server will call once it completes the operation. That is not covered here and I am leaving it to you to explore yourself. I am passing null for both the parameter. The return value is stored in the IAsyncResult. This is to do a check on the Server operation to make a safe call on the EndInvoke.

//Client 08: Call the remote method through the delegate. This is an Asynchronous call.
IAsyncResult AR = FnCounter.BeginInvoke(null , null);

7) After the above call, we are making a call to the local computer function. But, here the client after making a call to the PerfomCount using the BeginInvoke method on the delegate immediately moves to the next statement, which is a function-call for local counting.  So there is no waiting for the server to complete its task.

//Client 09: Call the Local Counter. The Local Counter also run in parallel now, and we no need to
//           wait for the remote call completion. The remote counting method, Once Done, calls our
//           call back method CallBackHandler.
LocalCounter();

8) Finally, after making both the function run simultaneously, we are waiting at the end of the routine to make a call to the EndInvoke, which is the pair of its corresponding BeginInvoke. The IsCompleted property of the return value of the BeginInvoke method is used to test whether server function tied to the delegate is finished or not. Once we know the server is done with the operation, we can make a call to EndInvoke by passing the value returned from the BeginInvoke function call.

//Client 10: Test the Remote counting is finished or Not before invoking the EndInvoke method on
//           the delegate
while (!AR.IsCompleted)
    Thread.Sleep(500);
FnCounter.EndInvoke(AR);

9) The entire event Handling routine for the Start Async button is shown below:

private void btnAsync_Click(object sender, EventArgs e)
{

    //Client 07: Create the proxy for remote Object and set the delegate to the required
    //           remote function.
    Counter cntObj = (Counter)Activator.GetObject(typeof(Counter), "tcp://localhost:13340/Counter");
    AsyncCall FnCounter = new AsyncCall(cntObj.PerformCount);

    //Client 08: Call the remote method through the delegate. This is an Asynchronous call.
    IAsyncResult AR = FnCounter.BeginInvoke(null , null);

    //Client 09: Call the Local Counter. The Local Counter also run in parallel now, and we no need to
    //           wait for the remote call completion. The remote counting method, Once Done, calls our
    //           call back method CallBackHandler.
    LocalCounter();

    //Client 10: Test the Remote counting is finsihed or Not before invoking the EndInvoke method on
    //           the delegate
    while (!AR.IsCompleted)
        Thread.Sleep(500);
    FnCounter.EndInvoke(AR);
}


5. Screen Shot of Sync and Async Call


Sync Call:




Note: The Server finished the count and Client not Yet Started.

Async Call:




Note: When the server is at the courting 32 and client is at 4533. It shows both the function is running in parallel.

Source code : Download

The above app is created in VS2005. If you have advanced IDE, Say yes to the conversion UI displayed.

Sunday, April 17, 2011

[C#] - Container Controls 2: Panel

1. Introduction to Panel Container


The "Container Control, Panel" is all about this article. We will see how do you use the panel control to group the controls and then we will explore the important properties of this container along with this example.

Panel container is almost like a group box and I am not going to discuss the stuff, which is already explained in the previous post for the groupbox. Unlike the groupbox, the panel does not have a title on the top. But it has the support to provide the scroll bars. These scrollbars allow you place plenty of control in it and make you scroll when the form is not enough to fit all the controls.

In this article example, we will see how the scroll bar behaves for some other property on the panel. OK let us start.


2. About the Sample


The form has a panel in the top and it displays a sample label placed on the design time. Below the panel there are two buttons one will add the label at runtime and the other one will remove the label.

The Allow auto size for panel check box, when checked, allows the panel to adjust its size based on the controls in it at the moment. Just think about how the auto size property of the label works. Panel also works the same way the content of the panel is controls, that’s all. The radio button Grow only and Grow and shrink controls how the automatic size of the panel behave.

The check box DoctoTop allows the panel to be docked on the topside of the form. This allows the panel to be resized when the form resizes.

Once the auto scroll check box is checked when the auto size is in the unchecked state the panel will get scroll bars. The Width and Height text boxes control the display of scroll bar.

This sample does not do any great thing and it is just created to explain the panel container and scrolling of the controls in it. OK. Let us move. Before that, download the sample and have look at the control names and properties set to it.



3. Docking the Panel


Docking is sticking the control to the any possible edges of the container. In our sample the Dockto Top checkbox will dock the panel to the top edge of the container. If a control is docked in the top or bottom of the container, the control width is always equal to its container. When container is resized the width of the docked control changed there by resizing it and the height will be constant. Similarly, if the control is docked in the Left or Right side of the container, the height will change along with the container and control width remains constant.

The code for the Check box UI is below:

private void checkBox1_CheckedChanged(object sender, EventArgs e)
{
    //Panel 01: Dock Property usage
    if (checkBox1.CheckState == CheckState.Checked)
        PanTopPane.Dock = DockStyle.Top;
    else
        PanTopPane.Dock = DockStyle.None;
}

The code sets the Dock property of the panel Control to top. Dockstyle.top is the enumeration constant. 

Why do I say the panel as control here? Well, the containers can behave as control also. Here, the Panel is a container for the sample label "label control". But the form treats the panel as a control or Panel’s container is the form. Simply, Form acts as container for the panel, and the panel acts as container for the  Label control. 

Dot net will see the "Dock Property" and knows where it should move and resize the control by looking at the container of the control. In our case, the panel is making a call to Dock() and Dot knows where to dock the panel as it knows the Container for the panel is the Form.

Run and Test > 01

1) Run the sample
2) Place a check mark on the Dockto Top
3) Now resize the form



Observe that the panel will resize along with the form only on the widthwise. Also, note that the panel is relocated from the design time position to the top of the form. Do not worry about the scroll bars now.

4. Panel autosize


The "AutoSize Property" of the panel will accept a Boolean true or false. When autosize is set to true, adding or removing the controls in the panel will automatically resize the panel. When this property is set to false and there is no scroll bar enabled to the container, the labels added beyond the visible portion will not be shown.

"AutoSizeMode Property" of the panel controls how the panel will be resized when the control is added to it or removed from it. The "GrowOnly Mode" of AutoSize property allows the panel to grow when the added control is in the invisible portion of the panel. And, the Panel Container will not shrink from the last set minimum size when a control is removed. The "GrowAndShrink mode" will allow the control freely resized based on addition or removal of the controls.

Below is the code for it:

private void chkAutoSize_CheckedChanged(object sender, EventArgs e)
{
    //Panel 02: Allow Auto Size to Panel. Then set the mode in which auto size works
    if (chkAutoSize.CheckState == CheckState.Checked)
        PanTopPane.AutoSize = true;
    else
        PanTopPane.AutoSize = false;
}

//Panel 03: Set the auto size mode
private void radGrowOnly_CheckedChanged(object sender, EventArgs e)
{
    if (radGrowOnly.Checked == true)
        PanTopPane.AutoSizeMode = AutoSizeMode.GrowOnly;
}

private void radGrowShrink_CheckedChanged(object sender, EventArgs e)
{
    if (radGrowShrink.Checked == true)
        PanTopPane.AutoSizeMode = AutoSizeMode.GrowAndShrink;
}

I hope no explanation is required on the code. You can understand it easily.

5. Adding and removing control at runtime


The panel and all the container classes maintain a collection of controls as property. The property name is "Controls". Here to add or remove the label controls we need to create control first and then add it to the panel through methods offered by the Controls property. Let us look at the code.

1) First, a variable is declared to know the position of the control when we add or remove. Here location_x will not change and when I am writing I am releasing it and I do not want to make a change now. The location_y will change when we add the label and remove it.

//Panel 05: Remember the Location for the Labels
int location_x;
int location_y;

2) In the constructor, we are setting the above variables from the control that is already available in the form for reference.

//Panel 06: Save the Location
location_x = LblReference.Location.X;
location_y = LblReference.Location.Y;

3) Next, the handler for the Add Label button will first create the label, sets the location using the variables talked in the previous two points, sets the size and text for it. Once the label is ready, it is added to the panel’s control collection. Rest the panel will do. Our job is to create the control and add it to the collection.

private void btnAddLabel_Click(object sender, EventArgs e)
{
    //Panel 07: Create the label and set its properties at runtime
    Label lbl = new Label();
    location_y = location_y + LblReference.Height + 11;
    lbl.Location = new Point(location_x, location_y);
    lbl.Size = new Size(LblReference.Width, LblReference.Height);
    lbl.Text = "Label " + location_y.ToString();

    //Panel 08: Add the control to the panel at runtime. This is to show you how the AutoSizeMode
    //          Propety for the panel Works
    PanTopPane.Controls.Add(lbl);
}

4) Below is the code for the removal of the label. Hope explanation is not required as it does the reverse of the previous one.

//Panel 09: Remove the label from the Panel
private void btnRemoveLabel_Click(object sender, EventArgs e)
{
    if (PanTopPane.Controls.Count == 0) return;
    Control.ControlCollection Controls_in_Panel = PanTopPane.Controls;
    Controls_in_Panel.RemoveAt(PanTopPane.Controls.Count - 1);
    location_y = location_y - LblReference.Height - 11;
}

Run and Test > 02

1) Run the sample by pressing the F5
2) When the form is visible, make sure the Allow Autosize for Panel checkbox is not checked.
3) Click the add Label to Panel button six times.
Only 4 labels were added and where is the next two? Here comes the usage of the autosize property.

4) Now check the add Label to Panel Checkbox.
Now you will see the remaining two controls. So the autosize property actually changes the size of the panel based on the content it has.

5) Now click the Remove Label from Panel button six times.
For the first two control removed, the panel got reduced in size. Then for other four controls removal the panel just maintains its size. It is because of the AutosizeMode property of the panel control. The Grow Only will not shrink the control from its original size. The original size is the one, which was before the change happened to it by the autosize property with the mode growonly.

6) Now check the radio button Grow and Shrink
7) Add six labels as you did previously by clicking the button
8) Remove the labels by clicking the corresponding button six times.
Now the Panel is reducing the size from its original size.




6. AutoScroll and AutoScrollMargin of Panel


The "AutoScroll Property" of the panel provides the scrollbars to the Panel when it is required. OK, "when it is required" is decided by the other property AutoscrollMargin. The scroll margin actually tells the minimum size allowed between the border of the control and edge of the panel. When the size further reduced by resizing the panel, a scroll bar will be added to it.

Below is the code for it.

//Panel 04: Set the autoscroll for the Panel.
private void chkAutoScroll_CheckedChanged(object sender, EventArgs e)
{
    if (chkAutoScroll.Checked == true)
        PanTopPane.AutoScroll = true;
    else
        PanTopPane.AutoScroll = false;

    //Oh!! I am lazy. You better type the numbers in the width and Height boxes.
    int width = int.Parse(txtWidth.Text);
    int height = int.Parse(txtHeight.Text);
    Size dimention = new Size(width, height);
    PanTopPane.AutoScrollMargin = dimention;
}

Note that the AutoScrollMargin accepts a size structure. And the structure defines scroll margin and instructs the panel when it should display the scroll bars. Look at the below picture:



To map it to our example, the black boxes are the controls and the gray box is the panel. A and B shown are scroll margins defined by AutoScrollMargin property. When the container resize operation hides the margin area, a scroll bar will be introduced when AutoScroll property is set to true.

Run and Test > 03 [Make sure autosize is unchecked]


1) Run the Sample
2) Place a check mark on dockto Top
3) Enter 300 in the width text box. Place a check mark on the Auto Scroll checkbox. This will show a Horizontal scroll bar because of the margin width of 300.
4) Scroll to the right of the Panel. The distance between the sample label edge and panel edge is 300. This is what we set in the ScrollMargin property. Have a look at the above drawing once again.
5) Scroll back again to the original position.
6) Add the label control by clicking the button multiple times. Notice that when the label added exceeds the edge of the panel a vertical scroll bar is added. Now scroll down to see the all controls.



Source Code : Download


Sunday, April 10, 2011

SQL 2005 - Group by, Order by, Having, Top With Ties Clause in SQL Server 2005


1. Introduction


In this article, we will explore the usage of the "Group By" and "Order By" clause. Also, we will see how does the TOP option behave with the Order by clause.

2. Example 01 – Order by


The below Example shows, the contact title is sorted in ascending order. This is done by using the Order By ContactTitle which is shown in the below example as the last line of query. The default is the ascending order.



3. Example 02 – Order by descending


The above query sorted the result in the Ascending order. Now look at the below example which sorts the same contact title column in descending order. We need to explicitly specify the "DESC" keyword in the Order By Clause.



4. Example 03 – Order by with more than one column


Now Look at the below example.



The query sorted the result based on two columns. First, it sorted the contact title in the ascending order and with-in that it sorted the result in descending order for the column Customer Id. The order by clause order by ContactTitle Asc, CustomerID Desc; in the above query has two columns, Contact Title first and Customer id next. Above screen shot shows [Red box] Contact title is sorted in ascending order. Look at the blue box; the result is sorted in descending order within the Marketing Assistance value of the Contact title.

5. Example 04 – Order by with Top


Now look at the below example that shows the usage of the "Top" clause in conjunction with the Order by clause.




In the above Query, we asked for top 10 records. SQL server first performs the sorting and then picks the top 10 records from it. The box shown in red indicates that it is not the complete records for the country Brazil. The next query shows how do you bring complete records for the column specified in the Order by clause.

6. Example 05 - Select top with ties


As discussed in the previous example, to bring the complete records for the country (used in the order by) that participate in the top 10, use the top 10 "with ties" option. Below is the query output:



7. Example 06 – Aggregate Function


"Aggregate functions" operate on the group of records and if a grouping is not specified it is applied to the entire records of a given table. The below example shows the usage of the count() function that tells how many records exists in the table in which it is called.



So, the result says product table has 77 records. You can also use the other aggregate function SUM, AVG for average, Min, Max, Count(*) for total records and Count(<column_name>) for count of Number rows which does not have null value for the <column_name>

8. Example 07 – Aggregate Function with where clause


The below example shows the usage of the aggregate function count on a query that used a “where” clause in it. First, the record filter is applied, then a count on the column Discontinued is calculated skipping the null entries in it during the count.



9. Example 08 – One more Example for Aggregate


The example below is same as the previous one except that we used a different aggregate function. The query is to get the to Unit price total of the product that falls under the category 2.




10. Example 09 – Aggregate with group by


All the aggregate function example shown above is applied to all the records returned by the query. So it considers the whole record set as a group and applied the grouping function such as sum, Min etc on it. The group by clause is used to get sub-group of the whole record set returned by the query.

The below query first groups all the records returned based on the Category Id. So if there are 3 categories then there will three subgroups. The count(ProductId) aggregate is applied on each group. So the result shows you number of product available in each category.





11. Example 10 – Aggregate with group by and Having clause


Have a look at the result of the above query. Now we will filter the product category, which has product count more than 10. As you know the count is an aggregate (Applied onset of records) & we cannot use a where clause to apply the filter on count aggregate. The filter should be performed on the on the group level.  The having clause works similar to the where clause. Simply, where clause is for filtering the records and "having clause" is to filter the sub-groups returned.

The below query will return the category which has more than 10 products.




12. Example 11 – How it works all together


Have a look at the below query and the result. There is nothing special in it. But, it has all you learnt in this article.



Below is the short explanation on how SQL server sees the above query and retrieves the data from the database:

  1. First, a column filter is applied and it takes only two columns CategoryID and ProductId.
  2. Then the Record filter is applied on the records using the condition specified in the where clause.
  3. Now the Filtered column and records formed in sub – groups using the CategoryId as the Group.
  4. After the group, a Not NULL count on ProductID on each sub-group based on CategoryId is calculated [Count(CategoryID)]
  5. The above-formed sub-group is again filtered based on the condition given in the Having clause.
  6. Finally, from what we have the sorting is performed. Here, the order by clause will do the sorting based on the sub-group count of valid productId.

Note: The above examples are formed using the NorthWnd Sample database. The SQL Script for NorthWnd is attached.



Like this site? Tell it to your Firend :)