70-561 - Working with disconnected data - searching and filtering

Filed under: , , , , by:

Almost every application works with some sort of disconnected data and the vast majority of those applications use DataSet and DataTable objects. Selecting, searching and filtering data are the most common operations that are performed on those objects. And from my experience I can tell that even a junior developer can code those operations, so you might think that there's no point to bring up this topic, but I also know from my experience that even some senior developers don't know (or sometimes remember) that you can accomplish the same thing in several different ways. And if I hear word "several ways", I automatically think that you'd better know and understand all those ways because it's more likely that there will be some questions on the exam testing it. That's why I created the chart below to better remember the differences between different ways data can be filtered and searched in an untyped DataTable object.


Now it should be easier to remember that Find method in DataView class returns and index of the found first record that matches the search criteria, whereas Find method in DataRowCollection class returns the searched record. Below is the small console application that demonstrates those methods / properties in action. Personally I'm a big fan of LINQ, since I can use the same syntax to filter or search no matter if I work with DataSet, DataContext, ObjectContext or other classes. Of course there are some additional methods to better work with each of those classes, but the query syntax is always the same - it's not that you have to remember if Find method is in DataView or DataRowCollection class and if it returns an integer value or a data row and if it looks up by primary key or sort key. But unfortunately most production applications use ADO.NET 2.0 API rather than LINQ or Lambda expressions - plus the 70-561 exam test both ADO.NET 2.0 and ADO.NET 3.5, therefore a professional developer should remember all the above solutions.


using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Data;
 
namespace Search_Filter_ADO_NET
{
class Program
{
 
static DataTable Create_Person()
{
DataTable dt = new DataTable("Person");
dt.Columns.Add(new DataColumn("FirstName",typeof(string)));
dt.Columns.Add(new DataColumn("LastName",typeof(string)));
dt.Columns.Add(new DataColumn("Age",typeof(int)));
return dt;
}
 
static void Populate_Person(DataTable dt)
{
dt.Rows.Add("Will", "Smith", 35);
dt.Rows.Add("Jack", "Daniels", 40);
dt.Rows.Add("John", "Ripper", 34);
dt.Rows.Add("Alice", "Wonderland", 40);
dt.AcceptChanges();
}
 
static void DataTable_Select(DataTable dt)
{
Console.WriteLine("Select results:");
DataRow[] rows = dt.Select("Age<40"); 
foreach (var row in rows)
Console.WriteLine("First name: {0} Last name: {1} Age: {2}",
row[0], row[1], row[2]);
}
 
static void DataRow_Find(DataTable dt)
{
Console.WriteLine("Rows.Find results:");
DataRow row = dt.Rows.Find("20"); 
if (row!=null)
Console.WriteLine("First name: {0} Last name: {1} Age: {2}",
row[0], row[1], row[2]);
}
 
static void DataView_Find(DataTable dt)
{
Console.WriteLine("DataView.Find results:");
DataView view = dt.DefaultView;
view.Sort = "Age";
int index = view.Find(40);
if (index>-1)
Console.WriteLine("First name: {0} Last name: {1} Age: {2}",
view[index][0], view[index][1], view[index][2]);
}
 
static void DataView_FindRows(DataTable dt)
{
Console.WriteLine("DataView.FindRows results:");
DataView view = dt.DefaultView;
view.Sort="Age";
DataRowView[] rowviews = view.FindRows(40);
foreach (var rowview in rowviews)
Console.WriteLine("First name: {0} Last name: {1} Age: {2}",
rowview[0], rowview[1], rowview[2]);
}
 
static void DataView_RowFilter(DataTable dt)
{
Console.WriteLine("DataView.RowFilter results:");
DataView view = dt.DefaultView;
view.RowFilter = "Age<40";
foreach (DataRowView row in view)
Console.WriteLine("First name: {0} Last name: {1} Age: {2}",
row[0], row[1], row[2]);
}
 
static void DataTable_Lambda(DataTable dt)
{
Console.WriteLine("DataTable.Lambda results:");
var rows = dt.AsEnumerable().Where(p => p.Field<int>(2) > 34);
foreach (var row in rows)
Console.WriteLine("First name: {0} Last name: {1} Age: {2}",
row[0], row[1], row[2]);
}
 
static void DataTable_Linq(DataTable dt)
{
Console.WriteLine("DataTable.Linq results:");
var rows = from p in dt.AsEnumerable()
where p.Field<int>(2) > 34
select p;
foreach (var row in rows)
Console.WriteLine("First name: {0} Last name: {1} Age: {2}",
row[0], row[1], row[2]);
}
 
static void Main(string[] args)
{
DataTable dtPerson = Create_Person();
Populate_Person(dtPerson);
DataTable_Select(dtPerson);
DataView_FindRows(dtPerson);
DataView_Find(dtPerson);
DataView_RowFilter(dtPerson);
DataTable_Lambda(dtPerson);
DataTable_Linq(dtPerson);
Console.Read();
}
}
}

0 comments: