
Pro CSharp 2008 And The .NET 3.5 Platform [eng]
.pdf
862 CHAPTER 24 ■ PROGRAMMING WITH THE LINQ APIS
static void LoadExistingXml()
{
//Build an XElement from string. string myElement =
@"<Car ID ='3'> <Color>Yellow</Color> <Make>Yugo</Make>
</Car>";
XElement newElement = XElement.Parse(myElement); Console.WriteLine(newElement); Console.WriteLine();
//Load the SimpleInventory.xml file.
XDocument myDoc = XDocument.Load("SimpleInventory.xml"); Console.WriteLine(myDoc);
}
■Source Code The LinqToXmlBasics example can be found under the Chapter 24 subdirectory.
Navigating an In-Memory Document
So, that this point you have seen various ways in which LINQ to XML can be used to create, save, parse, and load XML data. The next aspect of LINQ to XML we need to examine is how to navigate a given document to locate specific elements/attributes. While the LINQ to XML object model provides a number of methods that can be used to programmatically navigate a document, not too surprisingly LINQ query expressions can also be used for this very purpose.
Since you have already seen numerous examples of building query expressions, the next example will be short and sweet. First, create a new Console Application named NavigationWithLinqToXml and import the System.Xml.Linq namespace. Next, add a new XML document into your current project named Inventory.xml, which supports a small set of entries within the root <Inventory> element. Here is one possibility:
<?xml version="1.0" encoding="utf-8"?> <Inventory>
<Car carID ="0"> <Make>Ford</Make> <Color>Blue</Color> <PetName>Chuck</PetName>
</Car>
<Car carID ="1"> <Make>VW</Make> <Color>Silver</Color> <PetName>Mary</PetName>
</Car>
<Car carID ="2"> <Make>Yugo</Make> <Color>Pink</Color> <PetName>Gipper</PetName>
</Car>
<Car carID ="55"> <Make>Ford</Make> <Color>Yellow</Color>

CHAPTER 24 ■ PROGRAMMING WITH THE LINQ APIS |
863 |
<PetName>Max</PetName>
</Car>
<Car carID ="98"> <Make>BMW</Make> <Color>Black</Color> <PetName>Zippy</PetName>
</Car>
</Inventory>
Now, select this file within the Solution Explorer and use the Properties window to set the Copy to Output Directory property to Copy Always (to ensure a copy of the file ends up in your Bin folder). Finally, update your Main() method to load this file into memory using XElement.Load(). The local doc variable will be passed into various helper methods to modify the data in various manners:
static void Main(string[] args)
{
Console.WriteLine("***** Fun with LINQ to XML *****\n");
//Load the Inventory.xml document into memory.
XElement doc = XElement.Load("Inventory.xml");
//We will author each of these next...
PrintAllPetNames(doc);
Console.WriteLine();
GetAllFords(doc);
Console.ReadLine();
}
The PrintAllPetNames() method illustrates the use of the XElement.Descendants() method, which allows you to directly specify a given subelement you wish to navigate to in order to apply a LINQ query expression. Here we are selecting each PetName value and printing out the contents to the console:
static void PrintAllPetNames(XElement doc)
{
var petNames = from pn in doc.Descendants("PetName") select pn.Value;
foreach (var name in petNames) Console.WriteLine("Name: {0}", name);
}
The GetAllFords() method is very similar in nature. Given the incoming XElement, we define a where operator and select the all XElements where the Make element is equal to the value "Ford":
static void GetAllFords(XElement doc)
{
var fords = from c in doc.Descendants("Make") where c.Value == "Ford"
select c;
foreach (var f in fords) Console.WriteLine("Name: {0}", f);
}
Figure 24-12 shows the output of this program.

864 CHAPTER 24 ■ PROGRAMMING WITH THE LINQ APIS
Figure 24-12. LINQ to XML in action
Modifying Data in an XML Document
Finally, as you would hope, LINQ to XML provides numerous ways to insert, delete, copy, and update XML content. Adding new XElements to an existing XElement (or XDocument) is no harder than calling the Add() method, which adds the data to the end of the element/document. As an alternative, you can call AddFirst() to add the item to the top of the element/document or AddAfterThis()/ AddBeforeThis() to insert data at a specific location.
Updating or deleting content is also very straightforward. After constructing a LINQ query statement to identify the item (or items) you wish to tinker with, simply call ReplaceContent() (for updating) or Remove()/RemoveContent() (for deletion of data). By way of a simple example, consider the following code, which adds a set of new <Car> elements to the incoming XElement parameter:
static void AddNewElements(XElement doc)
{
// Add 5 new purple Fords to the incoming document. for (int i = 0; i < 5; i++)
{
//Create a new XElement
XElement newCar =
new XElement("Car", new XAttribute("ID", i + 1000), new XElement("Color", "Green"),
new XElement("Make", "Ford"), new XElement("PetName", "")
);
//Add to doc.
doc.Add(newCar);
}
// Show the updates.
Console.WriteLine(doc);
}
That wraps up our look at the major LINQ APIs that ship with .NET 3.5, and this chapter as well! Over the remainder of this book, you will find various LINQ queries where appropriate; however, be aware that each of the APIs examined here (LINQ to DataSet, LINQ to SQL, and LINQ to XML) are extensively documented in the .NET Framework 3.5 SDK documentation.
■Source Code The NavigationWithLinqToXml to XML example can be found under the Chapter 24 subdirectory.

CHAPTER 24 ■ PROGRAMMING WITH THE LINQ APIS |
865 |
Summary
This chapter extended your understanding of LINQ by introducing three LINQ-centric APIs. We began by examining how to transform an ADO.NET DataSet into a LINQ-compatible container using the AsEnumerable() extension method. Once you have extracted an IEnumerable<T> type, you are able to apply any flavor of LINQ query.
Closely related to LINQ to DataSet is the LINQ to SQL API. This aspect of LINQ not only allows you to apply query expressions to data held within relational databases, it also provides infrastructure that essentially encapsulates all trace of the underlying ADO.NET data types. As you have seen, the DataContext type can be used to perform all of the expected database operations, including invoking stored procedures.
We wrapped up by examining LINQ to XML. Similar to LINQ to SQL, this API can be used either to apply LINQ queries to data within an XML document or to build XML documents in a functional manner. The end result is an extreme simplification of how the .NET platform supports the manipulation of XML documents.




CHAPTER 25 ■ INTRODUCING WINDOWS COMMUNICATION FOUNDATION |
869 |
distributed computing solution, Microsoft eventually released Microsoft Transaction Server (MTS), which was subsequently renamed to COM+ at a later release.
Despite its name, COM+ is not only used by COM programmers—it is completely accessible to
.NET professionals. Since the first release of the .NET platform, the base class libraries provided a namespace named System.EnterpriseServices. Here, .NET programmers could build managed libraries that could be installed into the COM+ runtime in order to access the same set of services as a traditional COM+-aware COM server. In either case, once a COM+-aware library was installed into the COM+ runtime, it was termed a serviced component.
COM+ provides a number of features that serviced components can leverage, including transaction management, object lifetime management, pooling services, a role-based security system, a loosely coupled event model, and so on. This was a major benefit at the time, given that most distributed systems require the same set of services. Rather than forcing developers to code them by hand, COM+ provided an out-of-the-box solution.
One of the very compelling aspects of COM+ was the fact that all of these settings could be configured in a declarative manner using administrative tools. Thus, if you wished to ensure an object was monitored under a transactional context or belonged to a particular security role, you simply needed to select the correct check boxes.
While COM+/Enterprise Services is still in use today, this technology is a Windows-only solution that is best suited for in-house application development or as a back-end service indirectly manipulated by more agonistic front ends (e.g., a public website that makes calls on serviced components [aka COM+ objects] in the background).
■Note WCF does not currently provide a way to build serviced components. However, it does provide a manner for WCF services to communicate with existing COM+ objects. If you need to build serviced components using C#, you will need to make direct use of the System.EnterpriseServices namespace. Consult the .NET Framework 3.5 SDK documentation for details.
The Role of MSMQ
The Microsoft Message Queuing (MSMQ) API allows developers to build distributed systems that need to ensure reliable delivery of message data on the network. As we all know too well, in any distributed system there is the risk that a network server is down, a database is offline, or connections are lost for mysterious reasons. Furthermore, a number of applications need to be constructed in such a way that they hold message data for delivery at a later time (known as queuing data).
At first, MSMQ was packaged as a set of low-level C-based APIs and COM objects. As well, using the System.Messaging namespace, .NET programmers could hook into MSMQ and build software that communicated with intermittently connected applications in a dependable fashion. Last but not least, the COM+ layer incorporated MSMQ functionality into the runtime (in a simplified format) using a technology termed Queued Components (QC).
Regardless of which programming model you used to interact with the MSMQ runtime, the end result ensured that applications could deliver messages in a reliable and timely fashion. Like COM+, MSMQ is still certainly part of the fabric of building distributed software on the Windows operating system.
The Role of .NET Remoting
As mentioned, with the release of the .NET platform, DCOM quickly became a legacy distributed API. In its place, the .NET base class libraries shipped with the .NET remoting layer, represented by the System.Runtime.Remoting namespaces. This API allows multiple computers to distribute objects, provided they are all running the applications under the .NET platform.

870 CHAPTER 25 ■ INTRODUCING WINDOWS COMMUNICATION FOUNDATION
The .NET remoting APIs provided a number of very useful features. Most important was the use of XML-based configuration files to declaratively define the underlying plumbing used by the client and the server software. Using *.config files, it was very simple to radically alter the functionality of your distributed system simply by changing the content of the configuration files and restarting the application.
As well, given the fact that this API is useable only by .NET applications, you can gain various performance benefits, as data can be encoded in a compact binary format, and you can make use of the Common Type System (CTS) when defining parameters and return values. While it is possible to make use of .NET remoting to build distributed systems that span multiple operating systems (via Mono, briefly mentioned in Chapter 1 and detailed in Appendix B), interoperability between other programming architectures (such as J2EE) was still not directly possible.
■Note Previous editions of this text included an entire chapter devoted to the topic of the .NET remoting APIs. With the release of WCF, however, I have decided not to include this chapter in this edition. The chapter on .NET remoting APIs (titled “The .NET Remoting Layer”) can be obtained free of charge from the Apress website (http://www.apress.com) by those who have purchased this text.
The Role of XML Web Services
Each of the previous distributed APIs provided little (if any) support to allow external callers to access the supplied functionality in an agnostic manner. When you need to expose the services of remote objects to any operating system and any programming model, XML web services provide the most straightforward way of doing so.
Unlike a traditional browser-based web application, a web service is simply a way to expose the functionality of remote components via standard web protocols. Since the initial release of .NET, programmers have been provided with superior support for building and consuming XML web services via the System.Web.Services namespace. In fact, in many cases, building a feature-com- plete web service is no more complicated than applying the [WebMethod] attribute to each public method you wish to provide access to. Furthermore, Visual Studio 2008 allows you to connect to a remote web service with the click of a button (or two).
Web services allow developers to build .NET assemblies containing types that can be accessed via simple HTTP. Furthermore, a web service encodes its data as simple XML. Given the fact that web services are based on open industry standards (HTTP, XML, SOAP, etc.) rather than proprietary type systems and proprietary wire formats (as is the case with DCOM or .NET remoting), they allow for a high degree of interoperability and data exchange. Figure 25-1 illustrates the agnostic nature of XML web services.
Of course, no distributed API is perfect. One potential drawback of web services is the fact that they can suffer from some performance issues (given the use of HTTP and XML data representation), and they may not be an ideal solution for in-house applications where a TCP-based protocol and binary formatting of data could be used without penalty.
A .NET Web Service Example
For many years now, .NET programmers have created web services using the ASP.NET Web Service project template of Visual Studio, which can be accessed using the File New Web Site dialog box. This particular project template creates a commonly used directory structure and a handful of initial files to represent the web service itself. While this project template is very helpful to get you up and running, you are able to build a .NET XML web service using a simple text editor and test it immediately using the ASP.NET development web server, WebDev.WebServer.exe (Chapter 31 examines this utility in more detail).

CHAPTER 25 ■ INTRODUCING WINDOWS COMMUNICATION FOUNDATION |
871 |
Figure 25-1. XML web services allow for a very high degree of interoperability.
By way of a quick example, assume you have authored the following programming logic in a new file named HelloWebService.asmx (*.asmx is the default file extension for a .NET XML web service file). Once you have done so, save it into C:\HelloWebService.
<%@ WebService Language="C#" Class="HelloWebService" %> using System;
using System.Web.Services;
public class HelloWebService
{
[WebMethod]
public string HelloWorld()
{
return "Hello World";
}
}
While this simple service is hardly doing anything terribly useful, notice that the file opens with the WebService directive, which is used to specify which .NET programming language is used in the file, and the name of the class type representing the service. Beyond this, the only point of interest is that the HelloWorld() method has been decorated with the [WebMethod] attribute. In many cases, this is all you need to do to expose a method to external callers via HTTP. Finally, notice that you do not need to do anything special to encode the return value into XML, as this is done automatically by the runtime.
If you wish to test this web service, simply open up a Visual Studio 2008 command prompt and enter the following command (if you’d like to see each option you can use with this development web server, simply enter the -? argument):
webdev.webserver /port:8080 /path:"C:\HelloWebService"