Creating a Service with Windows Communication Foundation and LINQ to SQL
The .NET framework has thousands of discrete classes that are well-organized by namespaces. The .NET framework also has large chunky bits that are whole sub-systems within the framework. When you start combining these sub-systems, you get powerful solutions very quickly. In this article, you'll combine Windows Communication Foundation (WCF) introduced in .NET 3.0 and LINQ to SQL introduced in .NET 3.5 and learn how to implement a service on top of LINQ and SQL server with astonishingly few lines of code.
Using the WCF Service Application Applet
When the concept of wizards first showed up, I didn't like them that much. They seemed to produce a bunch of code that looked like magic, but this code was sometimes hard to modify and hard to reproduce. Newer wizards in Visual Studio with the .NET framework use framework code, producing lucid, and easy to follow bits of code. So, although you could create a WCF solution from scratch, let Visual Studio generate the starter code for you.
WCF uses the concept of a ServiceContract and a DataContract. The ServiceContract specifies the behaviors provided by your service and the DataContract describes data that will be introduced by the service. If you select File|New Project and pick WCF Service Library—in Visual Studio 2008—the templates and wizards will stub out all of the basic elements, demonstrating a sample ServiceContract and DataContract. This stubbed solution is ready to compile and test.
The WCF template defines an interface attributed with the ServiceContractAttribute, a class that is attributed with the DataContractAttribute, and a second a class that implements the ServiceContract interface. The DataContract class is a dummy class representing a composite type showing you how to implement custom types to be used in your service. Each behavior that you want to publish is described in the ServiceContract as a method and attributed with the OperationContractAttribute. Each property that you want to be serialized in the composite type—the DataContract—is attributed with the DataMemberAttribute. In short, OperationContractAttributes are callable by service consumers and DataMemberAttributes are serialized and accessible by those same consumers.
|If you change the name of service class,you must update the reference in the web.config and in the associated .svc file.|
Because Visual Studio stubs out all of this for you, you can move on to the code you have to write to implement a useful service.
Programming with LINQ to SQL Behind a WCF Service
Suppose now that you want to use LINQ to SQL behind the service. You will need a database (you'll use Northwind) and some basic plumbing for LINQ to SQL. The two basic LINQ to SQL elements you will need are a DataContext, representing the connection to the database, and an entity class (or DataSet) attribute with the TableAttribute. The TableAttribute indicates that the annotated class can be populated by the LINQ to SQL plumbing.
The key here is that the DataContract and the LINQ to SQL entity can be the same composite type. That is, you define one class and attribute it with WCF and LINQ to SQL attributes, resulting in both technologies being supported in the same class.
For your purposes, you will define a service that looks up a customer in the Northwind Traders database. The code that follows is bootstrapped with the WCF Visual Studio wizard template and the LINQ to SQL code was added. Listing 1 starts you off with the WCF ServiceContract.
Listing 1: The WCF ServiceContract definition (an interface).
<ServiceContract()> _ Public Interface ICustomerService <OperationContract()> _ Function GetCustomer(ByVal customerID As String) As Customer End Interface
Listing 2 implements the ServiceContract by providing an implementation of for GetCustomer.
Listing 2: A simple WCF ServiceContract that means you will be defining a service that returns customers by CustomerID.
Imports System.Data.Linq Public Class CustomerService Implements ICustomerService Public Sub New() End Sub Public Function GetCustomer(ByVal customerID As String) _ As Customer Implements ICustomerService.GetCustomer Dim northwind As Northwind = New Northwind() Dim customers As Table(Of Customer) = _ northwind.GetTable(Of Customer)() Dim customer = (From cust In customers _ Where cust.CustomerID = customerID _ Select cust).First() Return customer End Function End Class
To suport the LINQ code, a refernce to System.Data.Linq is added to the WCF library project. The LINQ code is a SQL-like query that shows (among other things) that you will need a class Northwind and a Table Customer. The rest is a LINQ query.
LINQ queries start with the From clause and end with a Select statement. You can think of this query as slecting customer by CustomerID. The .First() method call is an agrgegate operation that returns the first customer from the result set. (Because CustomerIDs are unique, this code should return just one Customer as long as the ID is valid.)
Page 1 of 3