Search This Blog

Tuesday, September 14, 2010

Store Procedure

In this article, we will examine what a stored procedure is and how to call one from SQL Server database.

Outline:
  • Why Use Stored Procedures?
  • Creating a Stored Procedure
  • Calling a Stored Procedure
  • Specifying Parameters
  • Data Retrieval
  • Inserting Data Using Parameters


Why Use Stored Procedures?

There are several advantages of using stored procedures instead of standard SQL. First, stored procedures allow a lot more flexibility offering capabilities such as conditional logic. Second, because stored procedures are stored within the DBMS, bandwidth and execution time are reduced. This is because a single stored procedure can execute a complex set of SQL statements. Third, SQL Server pre-compiles stored procedures such that they execute optimally. Fourth, client developers are abstracted from complex designs. They would simply need to know the stored procedure's name and the type of data it returns.

Creating a Stored Procedure

Enterprise Manager provides an easy way to create stored procedures. First, select the database to create the stored procedure on. Expand the database node, right-click on "Stored Procedures" and select "New Stored Procedure...". You should see the following:
CREATE PROCEDURE [OWNER].[PROCEDURE NAME] AS
Substitute OWNER with "dbo" (database owner) and PROCEDURE NAME with the name of the procedure. For example:
CREATE PROCEDURE [dbo].[GetProducts] AS
So far, we are telling SQL Server to create a new stored procedure with the name GetProducts. We specify the body of the procedure after the AS clause:
CREATE PROCEDURE [dbo].[GetProducts] AS
SELECT ProductID, ProductName FROM Products
Click on the Check Syntax button in order to confirm that the stored procedure is syntactically correct. Please note that the GetProducts example above will work on the Northwind sample database that comes with SQL Server. Modify it as necessary to suite the database you are using.

Now that we have created a stored procedure, we will examine how to call it from within a C# application.

Calling a Stored Procedure

A very nice aspect of ADO.NET is that it allows the developer to call a stored procedure in almost the exact same way as a standard SQL statement.

1. Create a new C# Windows Application project.

2. From the Toolbox, drag and drop a DataGrid onto the Form. Resize it as necessary.

3. Double-click on the Form to generate the Form_Load event handler. Before entering any code, add "using System.Data.SqlClient" at the top of the file.

Enter the following code:
private void Form1_Load(object sender, System.EventArgs e)
{
    SqlConnection conn = new SqlConnection("Data 
Source=localhost;Database=Northwind;Integrated Security=SSPI");
    SqlCommand command = new SqlCommand("GetProducts", conn);
    SqlDataAdapter adapter = new SqlDataAdapter(command);
    DataSet ds = new DataSet();
    adapter.Fill(ds, "Products");
    this.dataGrid1.DataSource = ds;
    this.dataGrid1.DataMember = "Products";
}
As you can see, calling a stored procedure in this example is exactly like how you would use SQL statements, only that instead of specifying the SQL statement, you specify the name of the stored procedure. Aside from that, you can treat it exactly the same as you would an ordinary SQL statement call with all the advantages of a stored procedure.

Specifying Parameters

Most of the time, especially when using non-queries, values must be supplied to the stored procedure at runtime. For instance, a @CategoryID parameter can be added to our GetProducts procedure in order to specify to retrieve only products of a certain category. In SQL Server, parameters are specified after the procedure name and before the AS clause.
CREATE PROCEDURE [dbo].[GetProducts] (@CategoryID int) AS
SELECT ProductID, ProductName FROM Products WHERE CategoryID = @CategoryID
Parameters are enclosed within parenthesis with the parameter name first followed by the data type. If more than one parameter is accepted, they are separated by commas:
CREATE PROCEDURE [dbo].[SomeProcedure] (
    @Param1 int,
    @Param2 varchar(50),
    @Param3 varchar(50)
) AS
...
For our GetProducts example, if @CategoryID was supplied with the value 1, the query would equate to:
SELECT ProductID, ProductName FROM Products WHERE CategoryID = 1
Which would select all the products that belong to CategoryID 1 or the Beverages category. To call the stored procedure, use Query Analyzer to execute:
exec GetProducts X
where X is the @CategoryID parameter passed to the stored procedure. To call the stored procedure from within a C# application using 1 as the @CategoryID parameter value, use the following code:
SqlConnection conn = new SqlConnection("Data 
Source=localhost;Database=Northwind;Integrated Security=SSPI");
SqlCommand command = new SqlCommand("GetProducts", conn);
command.CommandType = CommandType.StoredProcedure;
command.Parameters.Add("@CategoryID", SqlDbType.Int).Value = 1;
SqlDataAdapter adapter = new SqlDataAdapter(command);
DataSet ds = new DataSet();
adapter.Fill(ds, "Products");
this.dataGrid1.DataSource = ds;
this.dataGrid1.DataMember = "Products";
Note that you must now specify the CommandType property of the SqlCommand object. The reason we did not do this in the first example was that it is not required if the stored procedure does not accept parameters. Of course, specifying the CommandType property even if it is not needed may improve readability. The next line actually combines two lines in one:
command.Parameters.Add("@CategoryID", SqlDbType.Int);
command.Parameters["@CategoryID"].Value = 1;
The first line of this segment specifies that the command object (which calls the GetProducts stored procedure) accepts a parameter named @CategoryID which is of type SqlDbType.Int. The type must be the same as the data type specified by the stored procedure. The second line of this code segment gives the parameter the value 1. For simplicity, especially when using more than one parameter, I prefer to combine to two lines into a single line:
command.Parameters.Add("@CategoryID", SqlDbType.Int).Value = 1;
The rest of the code is the same as in the previous example without parameters. As illustrated in the previous examples, ADO.NET takes a lot of pain out of database programming. Calling a stored procedure uses virtually the same code as using standard SQL and specifying parameters is a painless process.

Data Retrieval

Data Retrieval with stored procedures is the same (surprise!) as if using standard SQL. You can wrap a DataAdapter around the Command object or you can use a DataReader to fetch the data one row at a time. The previous examples have already illustrated how to use a DataAdapter and fill a DataSet. The following example shows usage of the DataReader:
SqlConnection conn = new SqlConnection("Data 
Source=localhost;Database=Northwind;Integrated Security=SSPI");
SqlCommand command = new SqlCommand("GetProducts", conn);
command.CommandType = CommandType.StoredProcedure;
command.Parameters.Add("@CategoryID", SqlDbType.Int).Value = 1;
conn.Open();
SqlDataReader reader = command.ExecuteReader();
while (reader.Read())
{
    Console.WriteLine(reader["ProductName"]);
}
conn.Close();
Again, using either a DataAdapter or a DataReader against a query from a stored procedure is the same as specifying the SQL from within the code.

Inserting Data Using Parameters

Using other SQL statements such as INSERT, UPDATE or DELETE follow the same procedure. First, create a stored procedure that may or may not accept parameters, and then call the stored procedure from within the code supply the necessary values if parameters are needed. The following example illustrates how to insert a new user in a users table that has a username and password field.
CREATE PROCEDURE [dbo].[InsertUser] (
    @Username varchar(50),
    @Password varchar(50)
) AS
INSERT INTO Users VALUES(@Username, @Password)
string username = ... // get username from user
string password = ... // get password from user
SqlConnection conn = new SqlConnection("Data 
Source=localhost;Database=MyDB;Integrated Security=SSPI");
SqlCommand command = new SqlCommand("InsertUser", conn);
command.CommandType = CommandType.StoredProcedure;
command.Parameters.Add("@Username", SqlDbType.VarChar).Value = username;
command.Parameters.Add("@Password", SqlDbType.VarChar).Value = password;
conn.Open();
int rows = command.ExecuteNonQuery();
conn.Close();
First, we retrieve the username and password information from the user. This information may be entered onto a form, through a message dialog or through some other method. The point is, the user specifies the username and password and the applicaton inserts the data into the database. Also notice that we called the ExecuteNonQuery() method of the Connection object. We call this method to indicate that the stored procedure does not return results for a query but rather an integer indicating how many rows were affected by the executed statement. ExecuteNonQuery() is used for DML statements such as INSERT, UPDATE and DELETE. Note that we can test the value of rows to check if the stored procedure inserted the data successfully.
if (rows == 1)
{
    MessageBox.Show("Create new user SUCCESS!");
}
else
{
    MessageBox.Show("Create new user FAILED!");
}
We check the value of rows to see if it is equal to one. Since our stored procedure only did one insert operation and if it is successful, the ExecuteNonQuery() method should return 1 to indicate the one row that was inserted. For other SQL statements, especially UPDATE and DELETE statements that affect more than one row, the stored procedure will return the number of rows affected by the statement.
DELETE FROM Products WHERE ProductID > 50
This will delete all products whose product ID is greater than 50 and will return the number of rows deleted.

Conclusion

Stored procedures offer developers a lot of flexibility with many features not available using standard SQL. ADO.NET allows us to use stored procedures in our applications seamlessly. The combination of these two allows us to create very powerful appliations rapidly.

Thursday, September 9, 2010

Passing Data Between Forms

Introduction

Some of you would have faced a scenario where you wanted to pass data from one form to another in WinForms. Honestly, I too had a similar problem (that’s why I am writing this article!).
There are so many methods (How many? I don't know) to pass data between forms in Windows application. In this article, let me take four important (easiest) ways of accomplishing this:
  1. Using constructor
  2. Using objects
  3. Using properties
  4. Using delegates
Let us see all the above methods in detail in the following sections.
For data to be passed between forms using any of the above methods, we need two forms and some controls. Let us start by following the steps given below.

Step 1

Create a new project and select Windows application. This will create a default form as “Form1”. We can use this form for sending data.

Step 2

Add a textbox and a button to the form.

Step 3

Add another Windows Form for receiving the data and to display it. Right click the project and select Add->Add Windows Form. Enter a name or use the default name “Form2.cs” and click ok button.

Step 4

Add a label to the second form to display the text from form1.

The Constructor Approach

This could be the easiest method of all. A method is invoked whenever you instantiate an object. This method is called a constructor. Code a constructor for form2 class with one string parameter. In the constructor, assign the text to the label’s text property. Instantiate form2 class in form1’s button click event handler using the constructor with one string parameter and pass the textbox’s text to the constructor.
Follow the steps given below:

Step 1

Code a constructor for form2 class as below:

public Form2(string strTextBox)
{
  InitializeComponent(); 
  label1.Text=strTextBox;
}

Step 2

Instantiate form2 class in form1’s button click event handler as below:

private void button1_Click(object sender, System.EventArgs e)
{
    Form2 frm=new Form2(textBox1.Text);
    frm.Show();
}

The Object Approach

Objects are reference types, and are created on the heap, using the keyword new. Here we are going to pass data using objects. The approach is simple; in form2 we are going to instantiate form1 class.
Then instantiate form2 in the button click event handler of form1. After this we are going to pass form1 object to the form2 using form2’s form1 object. The last step is to invoke the form2 window by calling the form2’s show method.
Follow the below steps:

Step 1

Change the access modifier for textbox in form1 to public:

public class Form1 : System.Windows.Forms.Form
{  
 public System.Windows.Forms.TextBox textBox1;

Step 2

In the button click event-handler, add the following code:

private void btnSend_Click(object sender, System.EventArgs e)
{
    Form2 frm= new Form2();
    frm.frm1=this;
    frm.Show();
}

Step 3

In form2.cs, instantiate form1 class:

public class Form2 : System.Windows.Forms.Form
{
     private System.Windows.Forms.Label label1;
     public Form1 frm1;

Step 4

In Form2’s Load method, type cast the object (frm1) of form1 to Form1 and access form1’s textbox and assign its text to label’s text.

private void Form2_Load(object sender, System.EventArgs e)
{
    label1.Text=((Form1)frm1).textBox1.Text;
}

The Properties Approach

Properties allow clients to access class state as if they were accessing member fields directly, while actually implementing that access through a class method. In this method, we are going to add one property to each form. In form1 we are going to use one property for retrieving value from the textbox and in form2, one property to set the label’s text property. Then, in form1’s button click event handler, we are going to instantiate form2 and use the form2’s property to set the label’s text.
Follow the below steps:

Step 1

Add a property in form1 to retrieve value from textbox:

public string _textBox1
{
    get{return textBox1.Text;}
}

Step 2

Add a property in form2 to set the labels’ text:

public string _textBox
{
   set{label1.Text=value;}
}

Step 3

In form1’s button click event handler, add the following code:

private void button1_Click(object sender, System.EventArgs e)
{
     Form2 frm=new Form2();
     frm._textBox=_textBox1;
     frm.Show();
}

The Delegates Approach

Technically, a delegate is a reference type used to encapsulate a method with a specific signature and return type. You can encapsulate any matching method in that delegate. Here we are going to create a delegate with some signature and assign a function to the delegate to assign the text from textbox to label.
Follow the below steps:

Step 1

Add a delegate signature to form1 as below:

public delegate void delPassData(TextBox text);

Step 2

In form1’s button click event handler, instantiate form2 class and delegate. Assign a function in form2 to the delegate and call the delegate as below:

private void btnSend_Click(object sender, System.EventArgs e)
{
    Form2 frm= new Form2();
    delPassData del=new delPassData(frm.funData);
    del(this.textBox1);
    frm.Show();
}

Step 3

In form2, add a function to which the delegate should point to. This function will assign textbox’s text to the label:

public void funData(TextBox txtForm1)
{
    label1.Text = txtForm1.Text;
}

Friday, September 3, 2010

C# to give download link in gridview control

Source code fot gridview:-

   1:  <asp:GridView ID="grdsearch" runat="server" AutoGenerateColumns="False">
   2:                             
   3:<Columns>
   4: <asp:BoundField HeaderText="Full Name" DataField="FullName"/>
   5: <asp:BoundField HeaderText="Email ID" DataField="Email"/>
   6: <asp:BoundField HeaderText="Gender" DataField="Sex"/>
   7: <asp:BoundField HeaderText="Education" DataField="Education"/>
   8: <asp:BoundField HeaderText="Skills" DataField="Skillsetdetails"/>
   9: <asp:BoundField HeaderText="Total Experience" DataField="Totalexperience"/>
  10: <asp:BoundField HeaderText="Relvent Experience" DataField="Relventexperience"/>
  11: <asp:BoundField HeaderText="Address" DataField="Address"/>
  12: <asp:BoundField HeaderText="Previous Company Detail" DataField="Previousemployerdetail"/>
  13: <asp:BoundField HeaderText="Mobile Number" DataField="Mobileno"/>
  14: <asp:BoundField HeaderText="Availability" DataField="Availability"/>
  15: <asp:BoundField HeaderText="Currentctc" DataField="Currentctc"/>
  16: <asp:BoundField HeaderText="Expectedctc" DataField="Expectedctc"/>
  17: <asp:BoundField HeaderText="Preferred Location" DataField="StateName"/>
  18: <asp:BoundField HeaderText="Resume Name" DataField="ResumeName"/>
  19: <asp:TemplateField>
  20:  <ItemTemplate>
  21: <asp:LinkButton ID="LinkButton1" runat="server" Text="Resume Download" 
    CommandArgument='<%#Eval("Attachment")%>' OnCommand="btnDownload_Click">
  22:   
  23: asp:LinkButton>
  24:     ItemTemplate>
  25: asp:TemplateField>
  26:                  
  27:  Columns>
  28:  asp:GridView>

C# code to make file download on linkbutton click:-

 protected void btnDownload_Click(object sender, System.Web.UI.WebControls.CommandEventArgs e)
        {
            //Response.Write(e.CommandArgument.ToString());
            //Response.Write(e.CommandName.ToString()  );

            string queryString = e.CommandArgument.ToString();
            Response.Redirect(queryString);

        }