Introduction
In this article, a web service with HTTP binding is created, exposing a method that queries a database table using LINQ. The method is defined in the service contract of the WCF service. Each resulting record from the LINQ query is populated in an object that is defined in a data contract of the WCF service. The collection of objects is then returned by the service method as a generic IEnumerable
collection.
Defining the WCF Service
We first create the WCF service in Visual Studio 2008 and version 3.5 of .NET, using the wsHttp
binding. The service is defined in the web.config file, as follows:
<services>
<service name="SomeService" behaviorConfiguration="ServiceBehavior">
<endpoint address="" binding="wsHttpBinding" contract="ISomeService">
...
Note how the address attribute of the endpoint is left blank for now, letting IIS use a default address. This can be changed to a fixed address at deployment time.
We then define the service contract in the ISomeService.cs file. The service contract is where all the service methods are defined:
[ServiceContract]
public interface ISomeService
{
[OperationContract]
string GetData(int value);
[OperationContract]
IEnumerable<EmpRecord> GetEmpData(string empLastName);
}
We have two methods defined, the first one is just a simple method that returns a string
based on an int
passed in as an argument. The second method, which is the one that is of real interest to us, accepts a last name of an employee and returns a collection of EmpRecord
objects. The EmpRecord
class is defined in the data contract of the service, also in the ISomeService.cs file, as follows:
[DataContract]
public class EmpRecord
{
int id = 0;
string fName = "";
string lName = "";
string state = "";
[DataMember]
public int Id
{
get { return id; }
set { id = value; }
}
[DataMember]
public string First
{
get { return fName; }
set { fName = value; }
}
[DataMember]
public string Last
{
get { return lName; }
set { lName = value; }
}
[DataMember]
public string State
{
get { return state; }
set { state = value; }
}
}
The EmpRecord
class is defined as a data contract in the WCF service, with four private
fields and four corresponding public
properties to get and set the field values.
In the SomeService.cs file of the WCF project, we implement the service interface and methods that we defined above, as follows:
public class SomeService : ISomeService
{
public string GetData(int value)
{
return string.Format("You entered: {0}", value);
}
public IEnumerable<EmpRecord> GetEmpData(string empLastName)
{
LinqDataClassesDataContext ctxt = new LinqDataClassesDataContext();
return from r in ctxt.Employees
where r.lName.Contains(empLastName)
select new EmpRecord
{ Id = r.ID, First = r.fName, Last = r.lName, State = r.state};
}
}
A LINQ expression is used in the body of the GetEmpData
method to query the Employee
table, returning all rows that have their lName
fields containing the last name string passed in as an argument. The Employee
table is made up of the following fields: ID
, fName
, lName
, City
, and State
. All matching rows are returned by the method as an IEnumerable
collection. The LinqDataClassesDataContext
is defined in the DBML file of our WCF service project, which is basically a LINQ to SQL data context object. We created this data context object by visually dropping our database tables into the LINQ to SQL DBML file that we added to our WCF project.
Consuming the WCF Service
To consume the WCF service, we create an ASP.NET web application project, and add a service reference to it in the Solution Explorer. We then create an instance of the service and call the appropriate methods, such as:
protected void Page_Load(object sender, EventArgs e)
{
SomeSvc.SomeServiceClient someSrvc = new SomeSvc.SomeServiceClient();
var coll = someSrvc.GetEmpData("Evans");
GridView2.DataSource = coll;
GridView2.DataBind();
}
SomeSvc
is the name of the service reference that I added to my ASP.NET web app project, which gives us access to the client proxy class. I then call the GetEmpData
method, passing an employee last name, and bind the returned collection of matching EmpRecord
objects to a gridview.
Alternatively, we can just iterate through the collection of EmpRecord
objects, as shown below:
bool bFound = false;
foreach (SamSvc.EmpRecord empl in coll)
{
if (empl.State.IndexOf("FL") >= 0)
{
bFound = true;
break;
}
}
Points of Interest
- The simplicity of defining our own objects as data contracts in a WCF service, and making use of easy to use LINQ expressions to encapsulate returned database records in those objects.
- Similarly, service contracts make it fairly straightforward to define our own methods in the WCF service, accepting and returning our own defined objects.
History
- 22nd July, 2008: Initial post