Wellington FL All Things Techy 02/05/2007 M However, another way to return the first employee is to use theFirstproperty to manually select the first employeeelement: employees.Element
Trang 1LINQ to XML example
Create a new Visual Studio project On the form, add a text box and two buttons Set the properties of
the text box so that it is multi-line and has a vertical scroll bar Behind button1, add the following code:
XDocument riders = new XDocument (new XDeclaration("1.0", "utf-8", "yes"), new XComment("Riders for the year 2008"), new XElement("Riders",
new XElement("Rider", new XAttribute("Residence", "Florida"), new XElement("Name", "Ricky Carmich ael"), new XElement("Class", "450"),
new XElement("Brand", "Suzuki"), new XElement("Sponsors",
new XElement("Name", "Makita") )
), new XElement("Rider", new XAttribute("Residence", "California"), new XElement("Name", "Chad Reed"),
new XElement("Class", "450"), new XElement("Brand", "Yamaha"), new XElement("Sponsors",
new XElement("Name", "ProTaper") )
), new XElement("Rider", new XAttribute("Residence", "Mississippi"), new XElement("Name", "Kevin Windham"), new XElement("Class", "450"),
new XElement("Brand", "Honda"), new XElement("Sponsors",
new XElement("Name", "Factory Connection") )
), new XElement("Rider", new XAttribute("Residence", "Florida"), new XElement("Name", "James Stewart"), new XElement("Class", "450"),
new XElement("Brand", "Kawasaki"), new XElement("Sponsors",
new XElement("Name", "Renthal") )
) ) );
textBox1.Text = riders.ToString();
Trang 2Be sure to add the appropriate reference toSystem.XML.Linqin your form prior to running the
project:
using System.XML.Linq;
Before running the project, take a look at the code Notice that several of the classes were used to create
and define the XML For example, theXDocumentclass was used to create an XML document As well,
theXElementandXAttributeclasses were used to define the attributes and elements of the XML
document
Run the project and click button1 when the form displays The text box on the form will display the
following XML:
<! Riders for the year 2008 >
<Riders>
<Rider Residence="Florida">
<Name>Ricky Carmichael</Name>
<Class>450</Class>
<Brand>Suzuki</Brand>
<Sponsors>
<Name>Makita</Name>
</Sponsors>
</Rider>
<Rider Residence="California">
<Name>Chad Reed</Name>
<Class>450</Class>
<Brand>Yamaha</Brand>
<Sponsors>
<Name>ProTaper</Name>
</Sponsors>
</Rider>
<Rider Residence="Mississippi">
<Name>Kevin Windham</Name>
<Class>450</Class>
<Brand>Honda</Brand>
<Sponsors>
<Name>Factory Connection</Name>
</Sponsors>
</Rider>
<Rider Residence="Florida">
<Name>James Stewart</Name>
<Class>450</Class>
<Brand>Kawasaki</Brand>
<Sponsors>
<Name>Renthal</Name>
</Sponsors>
</Rider>
</Riders>
Isn’t that much easier than using the DOM?
Trang 3What about querying XML? Open Notepad or another text editor and type in the following:
<Employees>
<Employee id="1" Dept="0001">
<Name>Scott</Name>
<Address>
<Street>555 Main St.</Street>
<City>Wellington</City>
<State>FL</State>
</Address>
<Title>All Things Techy</Title>
<HireDate>02/05/2007</HireDate>
<Gender>M</Gender>
</Employee>
<Employee id="2" Dept="0005">
<Name>Steve</Name>
<Address>
<Street>444 Main St.</Street>
<City>Snahomish</City>
<State>WA</State>
</Address>
<Title>Mr SciFi</Title>
<HireDate>05/14/2002</HireDate>
<Gender>M</Gender>
</Employee>
<Employee id="3" Dept="0004">
<Name>Joe</Name>
<Address>
<Street>222 Main St.</Street>
<City>Easley</City>
<State>SC</State>
</Address>
<Title>All Things Bleeding Edge</Title>
<HireDate>07/22/2004</HireDate>
<Gender>M</Gender>
</Employee>
</Employees>
Save this file asEmployees.xml Next, add the following code behind button2 :
XElement employees = XElement.Load("Employees.xml");
textBox1.Text = employees.Element("Employee").ToString();
Run the project again and click button2 The text box will be filled with the first employee from the
XML document, as shown here:
<Employee id="1" Dept="0001">
<Name>Scott</Name>
Trang 4<Street>555 Main St.</Street>
<City>Wellington</City>
<State>FL</State>
</Address>
<Title>All Things Techy</Title>
<HireDate>02/05/2007</HireDate>
<Gender>M</Gender>
</Employee>
However, another way to return the first employee is to use theFirst()property to manually select
the first employeeelement:
employees.Elements("Employee").First()
Another alternative is to use theElementAt()method to specify which element to return:
employees.Elements("Employee").ElementAt(0)
Yet another method is to use a LINQ query expression:
XElement empnum2 = (from emp in employees.Elements("Employee")
where (int)emp.Attribute("id") == 2 select emp).ElementAt(0);
This example uses a LINQ query expression to query the XML document, using the attribute"id"as
a filter In this example, theElementAt()method is used to return the first element that matches the
specified criteria
This next example uses a LINQ query expression to query the XML document and return the values of
all theNameelements for each employee To get that information, thedescendants()method is used
to return a collection of all descendants for the selected element:
IEnumerable<string> empNames =
from emp in employees.Descendants("Name")
orderby emp.Value
select emp.Value;
foreach (string name in empNames)
listBox1.Items.Add(name);
When run, this example returns the following:
Joe
Scott
Steve
Trang 5Traversing XML
Traversing XML in an XML tree using LINQ to XML is quite simple Just use the methods of the
XElementandXAttributeclasses as necessary Basically, theElementsandElementmethods
provide all of the element children of anXContainer(anXElementorXDocument) object Using
theXNameobject, such asElement(XName), one can return elements of that specificXName
For example, using the XML document used in the previous example, one can ‘‘walk the XML tree,’’ as
shown here:
employees.Element("Employees").Element("Employee") employees.Element("Employees").Element("Employee") Element("Name")
The same can be accomplished with attributes as well The following illustrates how to walk an XML
tree to get to a specific attribute:
employees.Elements("Employee").ElementAt(1).Attribute("id")
The thing to remember is that theNodes(),Elements(),Element(Name), andElements(Name)
methods provide the foundation and basic functionality of XML tree navigation
LINQ to DataSet
Most, if not all, NET developers are familiar with the concept of aDataSetbecause it is one of the
most frequently used components in ADO.NET ADataSetis a representation of the tables and
rela-tionships found in a database, exposing a hierarchical object model made of objects such as tables, rows,
columns, constraints, and relationships
TheDatasetitself is extremely flexible and powerful It provides the capability for applications to
efficiently work with a subset of data found in a database and to manipulate the data as needed by the
application, all while in a disconnected state
Yet, with all the flexibility there has not been, up to this point, a means or method for querying data
contained within theDataSet(other than the few methods on theDataTableclass such asSelect,
GetParentRow, andGetChildRow) This is where LINQ and LINQ toDataSetcome in With the
querying power of LINQ, LINQ toDataSetprovides developers with a full set of query capabilities to
quickly and easily query the contents of aDataSet
An illustration of how easy it is to query aDataSetusing LINQ to DataSet follows
Querying a DataSet using LINQ to DataSet
First, create a new Visual Studio project Make sure that the project includes references to both the
System.CoreandSystem.Data.DataSetExtensionnamespaces On the form, place a button, a
text box, and a list box Add the followingusingstatement to the code as well:
using System.Data.SqlClient;
Trang 6Anyone who has worked with aDataSetis intimately familiar with how to populate it using the
SqlDataAdapter The following example uses theSqlDataAdapterto populate aDataSetwith
data from thePerson.Contacttable then use a LINQ query expression to query theDataSet
Add the following code to the Click event of the button:
try
{
//first, populate the dataset
DataSet ds = new DataSet();
string connectionInfo = "Data Source=SERVERNAME;Initial
Catalog=AdventureWorks;Integrated Security=sspi";
SqlDataAdapter da = new SqlDataAdapter("select pc.ContactID,
pc.FirstName, pc.MiddleName, pc.LastName, pc.EmailAddress from
Person.Contact pc", connectionInfo);
da.TableMappings.Add("Table", "Contact");
da.Fill(ds);
DataTable dt = ds.Tables["Contact"];
textBox1.Text = ds.Tables[0].Rows.Count.ToString();
//now query it for specific people
var con = from contact in dt.AsEnumerable()
where contact.Field<string>("FirstName") StartsWith("S")
select new { ContactID = contact.Field<int>
("ContactID"),
FirstName = contact.Field<string>
("FirstName"), MiddleName = contact.Field<string>("MiddleName"),
LastName = contact.Field<string>
("LastName"), Email = contact.Field<string>
("EmailAddress")};
foreach (var cont in con)
listBox1.Items.Add(cont.ContactID.ToString() + " " + cont.FirstName + " " +
cont.MiddleName + " " + cont.LastName + " " + cont.Email);
}
Trang 7catch (Exception ex) {
MessageBox.Show(ex.Message);
}
Compile the project to ensure there are no errors, and then run it When the form opens, click the
but-ton The text box will display the total number of records contained in theDataSet The list box will
fill with all the contacts from theDataSetwhose first name begins with the letter S
Note a couple of things here:
■ TheDataSetis not a typedDataSetbecause theField()method is used to access the column values of theDataRow
■ The LINQ query itself Like the others before it in this chapter, the syntax follows the same pattern as the other queries The only difference is the data source
■ The use of theAsEnumerable()method This method returns anIEnumerableobject, which in this case enables you to iterate over the data in theDataTable
The next example does two things One, it uses a typedDataSet Two, it adds a second table to the
DataSetthat illustrates how to use a LINQ query to query data from two tables
Add a new item to the solution, this time adding aDataSet In the Add New Item dialog, select Data
from the list of Categories, and then selectDataSetfrom the list of Templates Name theDataSet
ContactDS.xsdand click OK
The DataSet Designer will display in the Visual Studio IDE The DataSet Designer is a visual tool for
creating and editing typedDataSets and the individual items that make upDataSets The DataSet
Designer provides developers with a visual depiction of the objects contained in theDataSets
In the Dataset Designer, drag and drop theContactandEmployeetables from the Server Explorer
Next, modify the code behind the button as follows:
try { ContactsDS ds = new ContactsDS();
string connectionInfo = "Data Source=SERVERNAME;Initial Catalog=AdventureWorks;Integrated Security=sspi";
SqlDataAdapter da = new SqlDataAdapter("select * from Person Contact; select * from HumanResources.Employee;", connectionInfo);
da.TableMappings.Add("Table", "Contact");
da.TableMappings.Add("Table1", "Employee");
da.Fill(ds);
textBox1.Text = "contact table has " + ds.Tables[0].Rows.Count ToString() + " records, and employee table has " +
Trang 8ds.Tables[1].Rows.Count.ToString() + " records.";
var query =
from con in ds.Contact
join emp in ds.Employee
on con.ContactID equals emp.ContactID
where con.FirstName.StartsWith("S")
select new
{
ContactID = con.ContactID, FirstName = con.FirstName, LastName = con.LastName, EMail = con.EmailAddress, EmpID = emp.EmployeeID, IDNum = emp.NationalIDNumber, HireDate = emp.HireDate };
foreach (var cont in query)
listBox1.Items.Add(cont.ContactID.ToString() + " " +
cont.FirstName + " " + cont.LastName + " " + cont.EMail + " " + cont.EmpID + " " + cont.IDNum + " " + cont.HireDate.ToString());
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
Compile the project to ensure there are no coding errors, and then run it When the form displays, click
the button The text box will display a message indicating the number of records returned in each table
The list box will then display a combination of contact and employee data for all contacts whose first
name begins with the letter S
Before moving on to the last example, consider what the code is doing In many ways it is very similar
to the previous example, but several things are different:
■ This example uses a typedDataSet
■ Two tables are being populated, not just one
■ Because a typedDataSetis being used, it’s no longer necessary to use theField<>method
Instead, it employs a direct mapping to the tables and columns and the use of IntelliSense
■ The LINQ query expression uses thejoinstandard query operator to join theContacttable
and theEmployeetable
Trang 9One more comment about the prior example Because a typedDataSetwas used, theDataSetitself
contains the relationship information This can be visually seen on the DataSet Designer If a typed
datasethad not been used, then the relationship would have to be defined programmatically using
theDataRelationclass
Data binding with LINQ to DataSet
This section describes how to use LINQ to DataSet to do data binding This example is similar to the
first, in that it uses an untypedDataSet, but this is not the focus of the example because a typed
DataSetcan still be used The important thing to learn from this example is how to do data binding
using LINQ to DataSet
For this example, open the form in design view From the toolbox, drag and drop aDataGridViewcontrol
onto the form Place another button on the form and enter the following code in its Click event:
try { DataSet ds = new DataSet();
string connectionInfo = "Data Source=SERVERNAME;Initial Catalog=AdventureWorks;Integrated Security=sspi";
SqlDataAdapter da = new SqlDataAdapter("select pc.ContactID, pc.FirstName, pc.MiddleName, pc.LastName, pc.EmailAddress from Person.Contact pc", connectionInfo);
da.TableMappings.Add("Table", "Contact");
da.Fill(ds);
DataTable dt = ds.Tables["Contact"];
textBox1.Text = ds.Tables[0].Rows.Count.ToString();
IEnumerable<DataRow> contact = from con in dt.AsEnumerable() where con.Field<string>("FirstName").StartsWith("S") orderby con.Field<string>("LastName")
select con;
DataTable partialTable = contact.CopyToDataTable<DataRow>();
DataView dv = new DataView(partialTable);
dataGridView1.DataSource = dv;
} catch (Exception ex) {
MessageBox.Show(ex.Message);
}
Trang 10This example populates aDataSetwith all the data from theContactstable and then queries the
DataSetusing a LINQ query The query returns an enumeration ofDataRowobjects that is used to
populate aDataTablevia theCopyToDataTable()method Once theDataTableis populated,
a newDataViewis created and populated with the data in theDataTable TheDataViewis then
assigned to the DataSourceproperty of theDataGridView
Another option for binding would have been to bind theDataTabledirectly to theDataGridView,
as follows:
dataGridView1.DataSource = partialTable;
However, theDataViewprovides additional capabilities such as sorting and filtering data that is stored
in aDataTable
Additionally, the data can be bound by implicitly binding data to controls, by implementing the
IListSourceinterface This interface enables an object to return a list that is bindable to a data
source, as shown here:
var query =
from c in contact
where c.Field<string>("FirstName").StartsWith("S")
orderby c.Field<string>("LastName")
select c;
dataGridView1.DataSource = query;
Likewise, the following can be done:
BindingSource bindsrc = new BindingSource();
bindsrc.DataSrouce = query;
dataGridView1.DataSource = bindsrc;
Implicit binding is available because theTable<T>andDataQuery<T>classes have been updated to
implement theIListSourceinterface
All of these examples populated the initial DataSet with all of the records from the
Contacts table This was done by design to illustrate the querying capabilities of LINQ to
DataSet.
LINQ to Entities
When talking about LINQ to Entities, the discussion must also discuss the ADO.NET Entity Framework
This is because LINQ to Entities is the part of the ADO.NET Entity Framework that provides the LINQ
query capabilities
That statement then begs the question, what is the difference between LINQ to SQL and LINQ to
Enti-ties? In the LINQ to SQL section, it was stated that LINQ to SQL is an object-relational mapping
frame-work that enables the direct 1-to-1 mapping of SQL Server database objects to NET classes, where the
database closely resembles the application model