Updated on 02 Oct 2025 by Admin

Strongly Typed DataSet in ADO.NET

We know C# is itself a Type-Safe Language, meaning that the types of the variables are known at the compile time, so any operation between two unrelated types gives us a compile-time error, which is very good for developers, as they have time to correct the errors during the build time only.

Consider the following example:

int x=1;
string y="Sachin";
string z= x+y; // Not valid 

The third statement is absolutely not valid, as there is no meaning to add a string with an integer. However, we can always concatenate two strings, but the compiler is unaware of our actual requirement: whether we want to concatenate both variables as a string or add them. As a result, it throws a compilation-time error, which is self-explanatory and beneficial.

Getting compilation time errors is always better than catching them at run time. This is one of the benefits of a type-safe language. At the same time, if types are known at compilation time, we can easily access all the methods and properties of the type. Visual Studio also provides IntelliSense support for our convenience, making coding very friendly.

For example, if we declare a variable as a string, we can easily access all methods and properties of the string class on that variable. For instance, Length is a property of a string, so that we can use this property on any variable of type string. Similarly, ToUpper() is a method of the String class, so we can easily use it.

string Name="Sachin";
int length=Name.Length;
string NameUpper= Name.ToUpper();

Along the same line, Typed variables are always faster than the untyped variable or variable of an object type. Consider the following example:

private bool IsEqual(object x, object y)
{
return x.Equals(y);
}
bool IsValid= IsEqual(1,2);

The above code will decide whether two values are equal or not, but the actual type of variables will be known at runtime, and the compiler will make its decision. So, we can say that Objects are converted into the actual type at runtime. This process is called Unboxing.

Thus, with variables of object type, there is one additional disadvantage of boxing and unboxing.

We know that strongly-typed variables are always better than the object type variables, because of the following reasons:

  1. Gives IntelliSense support.
  2. Shows an error at compile time.
  3. Doesn't do boxing and unboxing.
  4. Class members like properties and methods become available for use.

Due to all of the above advantages, ADO.NET provides us a way to create typed datasets, which has a huge advantage over the untyped dataset. For example, consider the code below, which has been used to access a column value .

This accesses the EmployeeId column in the first row of the Employees table.

string EmployeeIdValue = EmployeesDataSet.Employees[0].EmployeeId;

In contrast, if you are working with an untyped dataset, the equivalent code is:

string customerIDValue = (string)dataset1.Tables["Customers"].Rows[0]["CustomerID"];

From the above code, it is very clear that with a typed dataset, accessing column values becomes much easier. Additionally, there is a need for conversion, and we also receive IntelliSense support, with errors displayed at compile time.

Steps to Generate a Typed Dataset using Visual Studio

  1. Right-click on the project name in the Solution Explorer and select "Add - New Item".
    Step1
    Step 1
  2. Select "DataSet", give it a meaningful name, and click "Add". This should add a file with .XSD extension.
    Step2
    Step 2
  3. Click on the "View" menu item in Visual Studio and select "Server Explorer"
    Step3
    Step 3
  4. In "Server Explorer", expand "Data Connections", expand the "Database", and lastly, expand "Tables".
    Step4
    Step 4
  5. Drag and drop the table based on which you want to generate a strongly typed dataset.
    Step5
    Step 5

Update Database Table with Typed DataSet

Let's discuss the same requirement that we have discussed in the previous article and try to achieve it with a strongly typed DataSet:

  • Step 1. Retrieve information of all employee from database.
  • Step 2. Display it in a GridView.
  • Step 3. Modify some of the information of some or all employees.
  • Step 4. View the changes in a grid.
  • Step 5. When you are completely satisfied with the changes, commit all the changes in the database in one go.

Go through the figure given below to understand the steps:

DataSet and DataAdapter   Example
DataSet example

  • Step 1. Retrieve data from database and bind the GridView.
  • protected void Page_Load(object sender, EventArgs e)
    {
    if (!IsPostBack)
    {
    BindGrid();
    }
    }
    private void BindGrid()
    {
    GridView1.DataSource = GetEmployee();
    GridView1.DataBind();
    }
    private EmployeeDataSet GetEmployee()
    {
    EmployeeDataSet ds = new EmployeeDataSet();
    if (Session["ds"] == null)
    {            
    using (SqlConnection con = new SqlConnection(cs))
    {
    SqlDataAdapter da = new SqlDataAdapter("select * from Employee", con);
    da.Fill(ds, "Employee");
    }
    Session["ds"] = ds;
    return ds;
    }
    ds = (EmployeeDataSet)Session["ds"];
    return ds;          
    }
    
    

  • Step 2. Modify details and save changes to the DataSet.
  • protected void GridView1_RowEditing(object sender, GridViewEditEventArgs e)
    {
    GridView1.EditIndex = e.NewEditIndex;
    BindGrid();
    }
    protected void GridView1_RowUpdating(object sender, GridViewUpdateEventArgs e)
    {
    EmployeeDataSet ds = GetEmployee();       
    ds.Employee[e.RowIndex].Name= e.NewValues[0].ToString();
    ds.Employee[e.RowIndex].Salary = Convert.ToInt32(e.NewValues[1]);
    ds.Employee[e.RowIndex].DepartmentId=Convert.ToInt32(e.NewValues[2]);
    Session["ds"] = ds;
    GridView1.EditIndex = -1;
    BindGrid();
    }
    protected void GridView1_RowCancelingEdit(object sender, GridViewCancelEditEventArgs e)
    {
    GridView1.EditIndex = -1;
    BindGrid();
    }
    
    

  • Step 3. On button Update click, commit all changes to the database.
  • protected void Button1_Click(object sender, EventArgs e)
    {
    using (SqlConnection con = new SqlConnection(cs))
    {
    SqlDataAdapter da = new SqlDataAdapter("select * from Employee", con);
    SqlCommandBuilder builder = new SqlCommandBuilder(da);
    da.Update((EmployeeDataSet)Session["ds"],"Employee");
    }
    }
    
    

Note: The DataAdapter's Update() method requires an Update command to update changes to the database. Here, we have used a SqlCommandBuilder object, which automatically builds an Update command based on the Select command used in a SqlDataAdapter.

The complete source code looks like below:

The Code Behind (aspx.cs)
public partial class StronglyTypedExample : System.Web.UI.Page
{
string cs = "Data Source=SACHIN-PC\\SQLEXPRESS;Initial Catalog=Test;Integrated Security=True";
protected void Page_Load(object sender, EventArgs e)
{
if (!IsPostBack)
{
BindGrid();
}
}
private void BindGrid()
{
GridView1.DataSource = GetEmployee();
GridView1.DataBind();
}
private EmployeeDataSet GetEmployee()
{
EmployeeDataSet ds = new EmployeeDataSet();
if (Session["ds"] == null)
{           
using (SqlConnection con = new SqlConnection(cs))
{
SqlDataAdapter da = new SqlDataAdapter("select * from Employee", con);
da.Fill(ds, "Employee");
}
Session["ds"] = ds;
return ds;
}
ds = (EmployeeDataSet)Session["ds"];
return ds;        
}
protected void GridView1_RowEditing(object sender, GridViewEditEventArgs e)
{
GridView1.EditIndex = e.NewEditIndex;
BindGrid();
}
protected void GridView1_RowUpdating(object sender, GridViewUpdateEventArgs e)
{
EmployeeDataSet ds = GetEmployee();   
ds.Employee[e.RowIndex].Name= e.NewValues[0].ToString();
ds.Employee[e.RowIndex].Salary = Convert.ToInt32(e.NewValues[1]);
ds.Employee[e.RowIndex].DepartmentId=Convert.ToInt32(e.NewValues[2]);
Session["ds"] = ds;
GridView1.EditIndex = -1;
BindGrid();
}
protected void GridView1_RowCancelingEdit(object sender, GridViewCancelEditEventArgs e)
{
GridView1.EditIndex = -1;
BindGrid();
}
protected void Button1_Click(object sender, EventArgs e)
{
using (SqlConnection con = new SqlConnection(cs))
{
SqlDataAdapter da = new SqlDataAdapter("select * from Employee", con);
SqlCommandBuilder builder = new SqlCommandBuilder(da);
da.Update((EmployeeDataSet)Session["ds"],"Employee");
}
}     
}

Aspx Page
<form id="form1" runat="server">
<div>
<asp:GridView ID="GridView1" runat="server" AutoGenerateColumns="False" DataKeyNames="Id"
OnRowCancelingEdit="GridView1_RowCancelingEdit" OnRowEditing="GridView1_RowEditing" OnRowUpdating="GridView1_RowUpdating">
<Columns>
<asp:CommandField ShowEditButton="True" />
<asp:BoundField DataField="Id" HeaderText="Id" InsertVisible="False" ReadOnly="True" SortExpression="Id" />
<asp:BoundField DataField="Name" HeaderText="Name" SortExpression="Name" />
<asp:BoundField DataField="Salary" HeaderText="Salary" SortExpression="Salary" />
<asp:BoundField DataField="DepartmentId" HeaderText="DepartmentId" SortExpression="DepartmentId" />
</Columns>
</asp:GridView>
<br />
<asp:Button ID="Button1" runat="server" Text="Commit Changes to Database" OnClick="Button1_Click" />
</div>
</form>

Now, run the application and modify some records. On Update button click, you will be successfully able to save changes to the database at one go.

So, what are strongly typed datasets

A typed DataSet is derived from the base DataSet class, so it inherits all of the functionality of the DataSet class. A typed DataSet is generated with the help of the DataSet Designer, which is stored in a .xsd file. As soon as we drop the table into the designer area, it first collects all the necessary information from the schema, such as tables, columns, and so on, and then compiles that into a new dataset class as a set of first-class objects and properties.

In brief, we can conclude:

  1. Strongly Typed Dataset is generated based on the Database Schema.
  2. Strongly Typed Dataset derive from DataSet.
  3. Like an ORM tool converts tables to classes, in a strongly typed dataset, the table columns become the properties of the DataSet class.

Advantage of Using Strongly-Typed Datasets over Untyped Datasets

  1. Since, in a strongly typed dataset, the database table columns become properties and the type associated with each column is also known at design time.
  2. Development is much easier as we have IntelliSense.
  3. Any errors related to misspelling column names can be detected at compile time, rather than at runtime.


You need to login to post a comment.

Sharpen Your Skills with These Next Guides