Tải bản đầy đủ (.pdf) (10 trang)

Hướng dẫn học Microsoft SQL Server 2008 part 84 docx

Bạn đang xem bản rút gọn của tài liệu. Xem và tải ngay bản đầy đủ của tài liệu tại đây (395.16 KB, 10 trang )

Nielsen c34.tex V4 - 07/23/2009 1:56pm Page 792
Part V Data Connectivity
LINQ 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();
792
www.getcoolebook.com
Nielsen c34.tex V4 - 07/23/2009 1:56pm Page 793
LINQ 34
Be sure to add the appropriate reference to System.XML.Linq in 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, the
XDocument class was used to create an XML document. As well,
the
XElement and XAttribute classes 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?
793
www.getcoolebook.com
Nielsen c34.tex V4 - 07/23/2009 1:56pm Page 794
Part V Data Connectivity
What 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 as Employees.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>
794
www.getcoolebook.com
Nielsen c34.tex V4 - 07/23/2009 1:56pm Page 795
LINQ 34

<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>
However, another way to return the first employee is to use the First() property to manually select
the first
employee element:
employees.Elements("Employee").First()
Another alternative is to use the ElementAt() 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, the
ElementAt() 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 the
Name elements for each employee. To get that information, the descendants() 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
795
www.getcoolebook.com
Nielsen c34.tex V4 - 07/23/2009 1:56pm Page 796
Part V Data Connectivity
Traversing XML
Traversing XML in an XML tree using LINQ to XML is quite simple. Just use the methods of the
XElement and XAttribute classes as necessary. Basically, the Elements and Element methods
provide all of the element children of an
XContainer (an XElement or XDocument) object. Using
the
XName object, such as Element(XName), one can return elements of that specific XName.
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 the Nodes(), 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 a DataSet because it is one of the

most frequently used components in ADO.NET. A
DataSet is 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.
The
Dataset itself 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 the
DataSet (other than the few methods on the DataTable class such as Select,
GetParentRow,andGetChildRow). This is where LINQ and LINQ to DataSet come in. With the
querying power of LINQ, LINQ to
DataSet provides developers with a full set of query capabilities to
quickly and easily query the contents of a
DataSet.
An illustration of how easy it is to query a
DataSet using 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.Core and System.Data.DataSetExtension namespaces. On the form, place a button, a
text box, and a list box. Add the following
using statement to the code as well:
using System.Data.SqlClient;
796
www.getcoolebook.com
Nielsen c34.tex V4 - 07/23/2009 1:56pm Page 797
LINQ 34
Anyone who has worked with a DataSet is intimately familiar with how to populate it using the
SqlDataAdapter. The following example uses the SqlDataAdapter to populate a DataSet with

data from the
Person.Contact table then use a LINQ query expression to query the DataSet.
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);
}
797
www.getcoolebook.com
Nielsen c34.tex V4 - 07/23/2009 1:56pm Page 798
Part V Data Connectivity
catch (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 the
DataSet. The list box will
fill with all the contacts from the
DataSet whose first name begins with the letter S.
Note a couple of things here:
■ The
DataSet is not a typed DataSet because the Field() method is used to access the
column values of the
DataRow.
■ 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 the
AsEnumerable() method. This method returns an IEnumerable object,
which in this case enables you to iterate over the data in the

DataTable.
The next example does two things. One, it uses a typed
DataSet. Two, it adds a second table to the
DataSet that illustrates how to use a LINQ query to query data from two tables.
Add a new item to the solution, this time adding a
DataSet. In the Add New Item dialog, select Data
from the list of Categories, and then select
DataSet from the list of Templates. Name the DataSet
ContactDS
.xsd and click OK.
The DataSet Designer will display in the Visual Studio IDE. The DataSet Designer is a visual tool for
creating and editing typed
DataSets and the individual items that make up DataSets. The DataSet
Designer provides developers with a visual depiction of the objects contained in the
DataSets.
In the Dataset Designer, drag and drop the
Contact and Employee tables 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 " +

798
www.getcoolebook.com
Nielsen c34.tex V4 - 07/23/2009 1:56pm Page 799
LINQ 34
ds.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 typed
DataSet.
■ Two tables are being populated, not just one.
■ Because a typed
DataSet is being used, it’s no longer necessary to use the Field<> method.
Instead, it employs a direct mapping to the tables and columns and the use of IntelliSense.
■ The LINQ query expression uses the
join standard query operator to join the Contact table
and the
Employee table.
799
www.getcoolebook.com
Nielsen c34.tex V4 - 07/23/2009 1:56pm Page 800
Part V Data Connectivity
One more comment about the prior example. Because a typed DataSet was used, the DataSet itself
contains the relationship information. This can be visually seen on the DataSet Designer. If a typed
dataset had not been used, then the relationship would have to be defined programmatically using
the
DataRelation class.
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 untyped
DataSet, but this is not the focus of the example because a typed
DataSet can 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 a
DataGridView control
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);
}
800
www.getcoolebook.com
Nielsen c34.tex V4 - 07/23/2009 1:56pm Page 801
LINQ 34
This example populates a DataSet with all the data from the Contacts table and then queries the
DataSet using a LINQ query. The query returns an enumeration of DataRow objects that is used to
populate a
DataTable via the CopyToDataTable() method. Once the DataTable is populated,
anew
DataView is created and populated with the data in the DataTable.TheDataView is then
assigned to the
DataSource property of the DataGridView.
Another option for binding would have been to bind the
DataTable directly to the DataGridView,
as follows:
dataGridView1.DataSource = partialTable;
However, the DataView provides additional capabilities such as sorting and filtering data that is stored
in a
DataTable.
Additionally, the data can be bound by implicitly binding data to controls, by implementing the
IListSource interface. 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 the Table<T> and DataQuery<T> classes have been updated to
implement the
IListSource interface.
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.
801
www.getcoolebook.com

×