Saturday, December 4, 2010

SQL Server 2008 - MERGE statement

SQL server 2008 has introduced a new feature to merge two tables. It lets you write a single SQL statement to insert, update and delete the records in the target table based on some conditions. It is very useful where you need to sync two tables. It avoids writing separate statements and logic for insert, update and delete.

It's syntax is very simple and straight forward:

MERGE <target_table> [AS table_alias]

USING <table_source> [AS table_alias]

ON <search_condition>

[WHEN MATCHED [AND clause_search_condition]

THEN <merge_matched> ]

[WHEN NOT MATCHED [BY TARGET] [AND clause_search_condition]

THEN <merge_not_matched> ]

[WHEN NOT MATCHED BY SOURCE [AND clause_search_condition]

THEN <merge_ matched> ];

Let me write an example and explain how MERGE works.

Let's say we have two tables named Books_Source and Books_Target which need to be synced periodically. And at one instance

The table Books_Source contains:

BookID BookName Quantity

1 "Learn ASP.Net" 3

3 "SQL tips" 5

4 "Complete Reference of JAVA" 2


The table Books_Target contains:

BookID BookName Quantity

1 "Learn ASP.Net" 2

2 "Learn XML" 4

4 "Complete Reference of JAVA" 4

To merge the above tables our MERGE statement goes like this:

MERGE Books_Target AS t

USING Books_Source AS s

ON t.BookID = s.BookID

WHEN MATCHED AND s.Quantity != t.Qunatity

THEN UPDATE SET t.Quantity = s.Quantity

WHEN NOT MATCHED BY TARGET

THEN INSERT(BookID, BookName, Quantity) VALUES(s.BookID, s.BookName, s.Quantity)

WHEN NOT MATCHED BY SOURCE

THEN DELETE;

  • As you can see in the above code, insert, update and delete actions happen in a single MERGE statement. It lets us add our own conditions to merge conflicts and our own merge actions to take place.
  • In this example we have written update statement where the records exist in both tables but the column Quantity is different. In this case I want to update only when quantity gets changed in Order_Source table.
  • Similarly we have written insert statement where the records exist in source table but not in target table. Here we have not added any additional condition because we wanted to insert all those don't exist in target table.
  • In the same way we have written DELETE statement where the records exist in target table but not in the source table. In this case we don't want the records those are not in source table.
  • MERGE statement is more efficient than separate statements for insert, update and delete operation to merge tables

The final result after the execution of above statement is:

BookID BookName Quantity
1 "Learn ASP.Net" 3
3 "SQL tips" 5
4 "Complete Reference of JAVA" 2

Wednesday, December 1, 2010

Jquery language translation plugin

Many of us know that Google is providing an online tool to translate from one language to another language. Of course this translation may not be accurate but the percentage of accuracy varies from language to language based on the language structure. Basically it translates word by word. This tool is really helpful to understand statements in different languages.

But if we have a our own website which is completely in English and there are users which don't know English and they want to know about our site then it is a problem. In this case they may not know that there is a tool which translates text in English to their native language or they don't have time to translate each and every page or they may not be interested to translate at all. Then they may simply skip reading and ignore your site.

To avoid these kind of risks Google also provided us translator API which lets us develop our website to translate from one language to another language. To know more about Google translator please go through the link http://code.google.com/apis/language/translate/v1/getting_started.html. It is very easy to integrate with our website by following this link.

But the major problem with the Google translate API is its limitation with the length of the text we pass to translator. It does not translate if we pass text with more than 5000 characters. It is only helpful where we need to translate a portion of our web page and that too with less than 5000 characters. If we have to translate the complete web page then we need to write complex logic to split the html code into 5000 character sets and translate thru API and then merge the results. This is really paining.

To solve these problems we have Jquery plugin for translator. You can download this at http://jquery-translate.googlecode.com/files/jquery.translate-1.3.9.min.js. It internally uses Google translator API and applies the above discussed logic and gives us the complete translated html. This takes the complex part and leave us a simplest part to translate complete web page.

The below code will do complete translation of your web page from source language to destination language

$('body').translate( srcLang, destLang );

Eg: $('body').translate( "en", "es"); //translates text from English to Spanish

But to get it working you also need to make sure you have Jquery along with this plugin.

You can also try playing with this plugin and see how it works. Please take a look at http://jsbin.com/emufo/edit and make any changes you want and preview the behavior by clicking Preview link on top left corner.

kick it on DotNetKicks.com

Wednesday, October 13, 2010

Online tool Url Decoder / Encoder

I have come across a need for url decoding as I got a link which was url encoded. And I have found a useful online tool which lets me enter a url encoded text and get the url decoded text. This also has functionality to url encode the given text. You may url encode as many times you want, but you need to decode the encoded text as number of times it was encoded.

I have found this as very useful for my purpose. And this works completely on client side. Please take a look at it.

http://meyerweb.com/eric/tools/dencoder/


Tuesday, October 5, 2010

Sitefinity performance factor - script manager

If you are using sitefinity to build any website then while adding sitefinity inbuilt controls such as menu you will be forced to write Script Manager in the template (master file). If you use script manager anywhere in the website it will load lot of unwanted javascript files along with the target page. It is better we don’t write script manager in any website unless we are building a complex website which needs ajax framework and other javascript libraries. I recommend you manually add menu and menu items in code rather than using sitefinity navigation controls and for ajax calls please use jquery to make server requests. Not having script manager will reduce the amount of javascript resources to a siginificant number.

And on our current project waypoint, we were not using any of the sitefinity inbuilt controls and not ajax framework too. But somehow we were having script manager written in the master file. And due to this it was loading around 350 KB javascript files which were never used by the site. And after I realised, I have removed the script manager tag and noticed a big surprise. The site is perfectly working without any issues and the overall page size was reduced from 500KB to 150KB (Avoiding 350KB for unwanted javascript files).
So I would strongly recommend you to avoid writing Script Manager in your websites and find the alternate solution for that.

kick it on DotNetKicks.com

Friday, July 9, 2010

Changing cookie expiration time

Changing cookie expiration time is not straight forward. It is not as easy as setting the http cookie's property Expires to required value as shown below.

HttpContxt.Response.Cookies["UserID"].Expires = DateTime.Now.AddMinutes(20);

I was using the above line of code in one of my projects as I wanted to make sure the cookie's expiration time gets updated for every user action. I added that line of code in the method where I check for authentication in each page request. But I was wondering with it's strange behavior as it is crashing the web page to load. I did spend some time on fixing it but got no luck.

After a while I got the solution which is explained in an MSDN article http://msdn.microsoft.com/en-us/library/ms178194.aspx. As explained the article, we must recreate the cookie with value and expiration time as we normally do when adding a cookie. So changing cookie is not at all different from creating a cookie in the browser. Finally I changed my code to recreate the cookie where updating cookie expiration time is needed. And it is perfectly working fine.

The correct code it worked was:

HttpContxt.Response.Cookies["UserID"].Value= UserID;
HttpContxt.Response.Cookies["UserID"].Expires = DateTime.Now.AddMinutes(20);

kick it on DotNetKicks.com

Tuesday, June 1, 2010

Installing Red5 on windows

Installing Red5 is easy as explained below.
  1. Before installing Red5 we need to make sure java is installed on the target machine. Because Red5 needs to java.
  2. If java is not installed then download the latest version of java and install it.
  3. Make sure the JAVA_HOME environment variable is set to the java installed root directory.
  4. To set the environment variable, right click "My Computer" in start menu/desktop and go to properties. Go to "Advanced" tab and there you will see a button named "environment variables" at bottom. Clicking it will open a dialog which will let you add your own variable. Click "New" button in the top section i.e., User variables and int the popup eneter JAVA_HOME for variable name and root directory of the java for variabl value as shown below
  5. Now you are ready to install the Red5. Download the latest version of Red5 from http://code.google.com/p/red5/ and install it.
  6. During the installation you may be asked to enter your ip address and port number (for version Red5 0.9.0 Final) to run the http protocol for Red5. You can enter your ip address or the dns name. But you must remember this as this is the one you need to use always. If you enter ip address during installation and use dns name in application then it will not work. You should use the one what you entered during installation. I don't know the reason but I experienced this. But if you are not asked to enter IP address (for version Red5 0.8.0 Final) then there will be no issues with the dns name to access the server. In this case the default port number is 8080.
  7. After Red5 installation is complete then you need to start the service.
  8. You can verify whether the Red5 is running and working fine by browsing to http://ip_address:port_number in any browser. The ip_address and port_numbers should be same as the ones entered during installation. Or the dns name and default port number 8080 will work work in the second case explained in the above step. If the server is working fine then you will be able to the server's home page which will talk about some demos, etc.

Audio recorder in website

One of our clients had a requirement having an audio recorder to be integrated with his website. He wanted record and playback features. This was challenging job to me and I did lot of research in this and finaly found one third party tool which serves exactly. The tool was FLV Audio Recorder developed by AVChat Software. You can get more details in it's website http://flvar.com/.

But this needs one the below media servers. Media servers are same as conventional web servers but they only deal with storing and streaming of videos, audios and images. Media servers use a different protocal called RTMP to accept the video/audio requests same as HTTP is used to accept various kinds of requests.

  1. Red5
  2. FMIS
  3. Wowza

The 1st media server listed above, Red5 is available for free and rest are expensive. I was interested to use Red5 as it was freely available.

To integrate the audio recorder in website I did the following:

  1. I got the 30-day trial version of FLV audio recorder. We need to request for trial version by filling a small form and they will email us with the download details of trial product. This will include a license key which needs to be entered in the product.
  2. I unzipped the archive and placed in some folder. And I created a virtual directory in IIS pointing to this folder. So I have verified all the files in audio recorder are accessed by webserver.
  3. I installed the Red5 media server as explained in the post http://cherupally.blogspot.com/2010/06/installing-red5-on-windows.html.
  4. I followed the installation instructions provided in http://flvar.com/documentation.
  5. I entered my license key in audiorecorder.properties file as instructed.
  6. I changed the avc_settings.php file to point to my red5 server.
  7. That's it. I am done with the integrating stuff. When I opened the audiorecorder-api.html file in browser I have noticed the audio recorder rendered in flash and functioning well.
  8. After completing all steps you may not get the audio recorder working until you reboot the machine. I had to reboot my machine to see the recorder working.



kick it on DotNetKicks.com

Friday, February 12, 2010

Bubbling up events from user control to parent page/control

It is a good practice to use user controls when same controls are repeated in many pages. But there are some cases where the user control has some controls which generate events and those need to be handled by the containing page/user control. For eample there is a button control in the user control and you want to do something in parent page/control when the button in user control is clicked. In this case

1.You need to define an event handler in user conrol as shown below.

public partial class UC_Pagination : System.Web.UI.UserControl
{
...
...

public event EventHandler PageIndexChanged;
...
...
...
}


2. You need to call the event explicitly in the user control's implementation of the event handler of button click as shown here

public partial class UC_Pagination : System.Web.UI.UserControl
{
...
...
protected void Button1_Click(object sender, EventArgs e)
{
...
...
PageIndexChanged(sender, e);
...
...
}
...
...
...
}

3. Implement the event handler bubbled up by user control in the parent page/control in its own way as usual (shown below).


public partial class Coaches : System.Web.UI.Page
{
...
...
protected void ucPaginationPageIndexChanged(object sender, EventArgs e)
{
...
...
...
}

...
...
}

kick it on DotNetKicks.com
Shout it

How to implement paging with LINQ

Before going into how paging is implemented with LINQ, Let's discuss the need for implementing paging.

With large amounts of data, it is not a good practice to pull all records from database when you are showing a fraction of them in one page. It is always recommended to use data on demand approach. When you want to show first 20 records out of the search results then you must get the first 20 records from database and discard the rest. Similarly when you want to show next 20 records of the search results then you need to get the next 20 records from database and discard the rest. This is nothing but called paging.

LINQ has made the paging solution very simple as shown below example.

public List<Client>
GetAllClients(bool? isActive, int pageNumber, int pageSize, out int totalPages)
{
//Actual query which returns large data
var query = dataContext.Clients.Where(p => isActive == null || p.IsActive == isActive);

//Calculating total number of pages by taking ceiling number of the fractional value
totalPages = (int)Math.Ceiling((decimal)query.Count() / (decimal)pageSize);

//Paging logic goes here
return query.Skip((pageNumber - 1)*pageSize).Take(pageSize).ToList();
}


The parameters which play major role in paging are page number and page size. The page number is to identify the page of which the records to be returned. And the page size to identify the number of records to be returned. And there is another out parameter totalPages which is used to hold the total number of pages available within the data returned. This is needed to show the number of pages to the user and also useful in the logic which enables/disables page navigation.
Shout it
kick it on DotNetKicks.com