Designing WCF DataContract Classes Using the LINQ to SQL Designer
This is my sixth article in a series focusing on Silverlight 2.0 development using Visual Studio 2008. In this article, we will leverage the power of the “LINQ to SQL Designer” by creating WCF-related “DataContract” classes visually. Finally, we will consume the same using a simple Silverlight 2.0 application.
This article assumes that you have minimum knowledge of technologies like "LINQ to SQL," "WCF," "Silverlight" and so forth. If you don't, and you need step by step instructions for the above technologies, please go through the following links.
The entire source code for this article is available in the form of a free downloadable zip file. The solution was developed using Microsoft Visual Studio 2008 Team Edition (with SP1) with Microsoft SQL Server 2008 Developer Edition, on Microsoft Windows Server 2003 Standard Edition (with SP2) with Silverlight 2.0 (RTM). I didn't really test it in any other environment. I request that you post in the discussion area if you have any problems in execution.
The entity classes (which hold information) are called DataContract classes in WCF. If the WCF Service has many DataContract classes, we will generally code them manually. The class designer can help us to a certain extent, but not a lot.
I have authored quite a few articles on "LINQ to SQL" on this web site. It is another great technology from Microsoft which enables us to create a DAL (Data Access Layer) in a RAD manner. Now we have the LINQ to SQL Designer. It is very similar to a class designer. However, it is tightly integrated with database objects.
In all of my previous articles, I used "LINQ to SQL" or "LINQ to SQL Designer" to simply leverage the capabilities of a DAL. However, we can also use the designer to quickly create WCF-supported "DataContract" classes visually and much more efficiently than a class designer.
Let us start creating a new solution to demonstrate this:
Create a new Visual Studio 2008 solution.
Add a new WCF Service project named "DemoEmpService."
Modify all "Service1" to "EmpService" everywhere in the project (steps are shown in my previous articles).
Add a "LINQ to SQL Classes" item to the project ("DemoEmp.dbml").
Using "Server Explorer," drag and drop "Emp" and "Dept" tables as shown in the following figure.
The above automatically creates the respective database context, along with "DataContract" classes with respect to "Emp" and "Dept." Make sure that you don't forget to set "SerializationMode" to "UniDirectional" (otherwise it won't create "DataContract" classes).
Okay. Sometimes, we may need to create some custom strongly-typed DataContract classes. These DataContract classes may not have any object directly related to the database (they may be part of a business information exchange). Even in these scenarios, we can make use of the LINQ to SQL designer.
Add one more "LINQ to SQL Classes" item to the project ("EmpViews").
Drag and drop a "Class" item from the toolbox on to the "LINQ to SQL Designer" surface.
Rename the class to "EnameDname" and add two properties (by right clicking on the class in the designer), "Ename" and "Dname."
Set the "SerializationMode" to "UniDirectional" for the context.
Save the DBML.
At this point, if you open the "EmpViews.designer.vb," you should see the "EnameDname" class defined as the "DataContract" class as follows:
<Table(Name:=""), _
DataContract()> _
Partial Public Class EnameDname
Private _Ename As String
Private _Dname As String
Public Sub New()
MyBase.New
End Sub
<Column(Storage:="_Ename", CanBeNull:=false), _
DataMember(Order:=1)> _
Public Property Ename() As String
Get
Return Me._Ename
End Get
Set
If (String.Equals(Me._Ename, value) = false) Then
Me._Ename = value
End If
End Set
End Property
<Column(Storage:="_Dname", CanBeNull:=false), _
DataMember(Order:=2)> _
Public Property Dname() As String
Get
Return Me._Dname
End Get
Set
If (String.Equals(Me._Dname, value) = false) Then
Me._Dname = value
End If
End Set
End Property
End Class
The above class can be directly used as a "WCF data contract object exchange" without any modification.
In the previous section, we have seen how we can create "DataContract" classes easily using the "LINQ to SQL Designer." Now, the goal is to access the same in a Silverlight application.
Modify IEmpService.vb as follows:
<ServiceContract()> _
Public Interface IEmpService
<OperationContract()> _
Function GetEnameDname() As List(Of EnameDname)
End Interface
Modify "EmpService.vb" as follows:
Imports System.Data.Linq
Public Class EmpService
Implements IEmpService
Public Sub New()
End Sub
Public Function GetEnameDname() As System.Collections.Generic.List(Of EnameDname) Implements IEmpService.GetEnameDname
Using ctxt As New DemoEmpDataContext
ctxt.ObjectTrackingEnabled = False
Return (From p In ctxt.Emps _
Select New EnameDname With {.Ename = p.Ename, .Dname = p.Dept.Dname}).ToList
In the previous sections, we have seen how to work with "DataContract" classes using the "LINQ to SQL Designer." In this section, I will extend the same with inheritance.
We can also inherit existing DataContract classes and create new sub DataContract classes visually using the "LINQ to SQL Designer." Open the previously-created "EmpViews.dbml" and create a new class (EnameDnameSal) with inheritance as shown below:
Once it is created, we should have a new class created in "EmpViews.Designer.vb" as follows:
<DataContract()> _
Partial Public Class EnameDnameSal
Inherits EnameDname
Private _Sal As Double
Public Sub New()
MyBase.New
End Sub
<Column(Storage:="_Sal"), _
DataMember(Order:=1)> _
Public Property Sal() As Double
Get
Return Me._Sal
End Get
Set
If ((Me._Sal = value) _
= false) Then
Me._Sal = value
End If
End Set
End Property
End Class
In the above class, you must observe the "inherits" statement in the class declaration. It is automatically added by the designer!
In the previous section, we saw how we can inherit existing "DataContract" classes easily using the LINQ to SQL Designer. Now, we need to have this show up in a Silverlight application.
Modify IEmpService.vb so that it looks like the following:
<ServiceContract()> _
Public Interface IEmpService
<OperationContract()> _
Function GetEnameDname() As List(Of EnameDname)
<OperationContract()> _
Function GetEnameDnameSal() As List(Of EnameDnameSal)
End Interface
Add a new method to EmpService.vb as follows:
Public Function GetEnameDnameSal() As System.Collections.Generic.List(Of EnameDnameSal) Implements IEmpService.GetEnameDnameSal
Using ctxt As New DemoEmpDataContext
ctxt.ObjectTrackingEnabled = False
Return (From p In ctxt.Emps _
Select New EnameDnameSal With {.Ename = p.Ename, .Dname = p.Dept.Dname, .Sal = p.Sal}).ToList
End Using
End Function
Modify the existing markup so that it looks like the following:
Private Sub EmployeeListFetched(ByVal sender As Object, ByVal e As EmpService.GetEnameDnameSalCompletedEventArgs)
Me.dgEmpDept.ItemsSource = e.Result
Me.lblMsg.Text = "Fetched!"
End Sub
End Class
In my upcoming articles, we will see more and more examples of Silverlight 2.0 development together with LINQ to SQL and WCF. I hope you enjoyed the article and any suggestions, bugs, errors, enhancements etc. are highly appreciated at http://jagchat.spaces.live.com