Sunday, January 25, 2009
NOTE: THIS IS THE READ ME FROM OUR NEW WCF DEMO INCLUDED IN THE ES2009 RELEASE CANDIDATE
 
Welcome to the

EntitySpaces 2009 Q1 WCF Demo

Created by Jon Davis for EntitySpaces, LLC

Contents

Introduction

This sample solution includes a set of projects that illustrate the use of EntitySpaces with Windows Communication Foundation (WCF), which is a technology featureset that arrived when Microsoft .NET 3.0 was released.

This demo is based on .NET 3.5 / Visual Studio 2008. It does not delve into WCF education or theory; it is only a "getting started" sample application that demonstrates how EntitySpaces objects can be used in a WCF architecture.

This is a lightweight sample that does not demonstrate more complex scenarios, such as working with data objects with one-to-many relationships.

Quick Start

This section is provided for those who just want to get the demo up and running and don't want to delve into the details.

To run the demo:

  1. Check the References of each project. If any of the EntitySpaces assembly references are broken (i.e. showing the "missing" icon), you will need to re-reference them. They should be in:
       %ProgramFiles%\EntitySpaces 2009\Runtimes\.NET 3.5\
  2. Make sure SQL Server Express is installed locally, and that you are a SQL Server admin. If the server is not running as ".\SQLExpress" you need to edit the app.config file in the ES2009WCF_Server project and rebuild the solution after reviewing #1 (above).
  3. In Visual Studio's Solution Explorer, right-click on the project called ES2009WCF_Server and choose Set as StartUp Project.
  4. Start Debugging. If you don't run into any errors and all is well, go ahead and shut it down (hit ENTER and let it quit).
  5. In Windows Explorer, track down the server's EXE file. It should be something like %DEMO%\ES2009WCF_Server\bin\Debug\ES2009WCF_Server.exe. Run it.
  6. In Visual Studio, for each of the client projects (each of the projects that are suffixed with "Client"), expand "Service References and right-click on the service reference item (should be something like "ESDemoService") and choose Update Service Reference.
  7. Stop the server process you started two steps previously (hit ENTER and let it shut down).
  8. Choose one of the client projects (any project suffixed with "Client") that you would like to run, right-click it, and select "Set as StartUp Project".
  9. Rebuild Solution.
  10. Start Debugging. The demo server will start automatically (after a prompt).

Troubleshooting:

  1. If with any client project you get an exception saying something followed by ".. The client and service bindings may be mismatched," stop the debugger, keep the server running, and right-click the service reference item in the project (in Solution Explorer) and choose Update Service Reference.
  2. If after the server starts successfully you get a System.ServiceModel.EndpointNotFoundException with a message "Could not connect to http://localhost:8731/ESDemoService/Light/. TCP error code 10061: No connection could be made because the target machine actively refused it 127.0.0.1:8731," you will need to temporarily disable Windows Firewall or poke a hole on port 8731 and/or on behalf of all EXE's involved.
  3. Be sure to restart the demo server's .EXE (or just kill it and let the demo client start it) as it may get locked in a Faulted state if an exception occurrs.

To create WCF projects:

  1. With EntitySpaces DLLs referenced on the client:
    • You will be using the Full / Heavy Proxies on both client and server. These are included with EntitySpaces' Master template.
    • You should use a shared library to be used on both client and server containing your generated business objects.
    • WCF will automatically serialize/deserialize and bind to your EntitySpaces-based library.
    • You will be able to use the Query object using manual binary serialization. (You cannot use XML serialization of the Query object in the ES2009 Q1 release, but XML serialization is planned for Q2.)
    • For a service sample, refer to demo project ES2009WCF_Server, file Full->ESDemoService_Full.cs.
      • The service was created by right-clicking on the project, choosing WCF Service, and then replacing the DoWork() method with real methods, both on the interface file and on the class.
    • For a client sample, refer to demo project ES2009WCF_Full_ConsoleClient or ES2009WCF_Full_WinFormsClient.
      • The WCF client was bound by manually starting the server app (ES2009WCF_Server.exe) from Windows Explorer, right-clicking on the client project in Visual Studio, choosing "Add Service Reference...", entering the service URL as shown on the server app console (this is set in the server app's app.config), clicking "Go", expanding the tree, selecting the interface, and choosing OK.
      • By default, the Service Reference configuration has "Reuse types in referenced assemblies" checked.
  2. Without EntitySpaces DLLs referenced on the client:
    • You will be generating Lightweight Proxies for your clients. These are created from EntitySpaces' generator seperately by expanding the ProxyStub tree branch (in the Templates tab) and running the Client Side Proxy/Stub.
    • The server will still use the Full / Heavy Proxies; however, ...
    • You should plan on serializing/deserializing your objects manually, both on client and server. A wrapper class called XmlSerialized<T> is provided with the demo to make this easier.
    • You will not be able to use the Query object in the ES 2009 Q1 release.
    • For a service sample, refer to demo project ES2009WCF_Server, file Light->ESDemoService_Light.cs.
      • The service was created by right-clicking on the project, choosing WCF Service, and then replacing the DoWork() method with real methods, both on the interface file and on the class.
    • For a client sample, refer to demo project ES2009WCF_Light_ConsoleClient.
      • The WCF client was bound by manually starting the server app (ES2009WCF_Server.exe) from Windows Explorer, right-clicking on the client project in Visual Studio, choosing "Add Service Reference...", entering the service URL as shown on the server app console (this is set in the server app's app.config), clicking "Go", expanding the tree, selecting the interface, and choosing OK.
      • The sample app demonstrates how serialization/deserialization was performed with the lightweight proxies.

Pre-Setup

This demo requires SQL Server 2005 (Express, Standard, or Enterprise edition) to be installed and running on the machine you are running the demo on. (You can get SQL Server Express edition for free at http://www.microsoft.com/express/sql/default.aspx.)

Your SQL Server instance needs to recognize you as an administrator, as the demo server will auto-create the database and database tables when it runs. You can remove this behavior and create the demo database and table(s) manually by opening the app.config file in the ES2009WCF_Server project and changing the appSettings values of createDatabase and resetTableData to false.

If you do decide to create the database and table manually, here is how it should be configured. The database name should be ES2009WCFDemo. You should have the following table structure(s):

USE [ES2009WCFDemo]

/****** Object:  Table [dbo].[Employee]    Script Date: 01/21/2009 17:30:16 ******/
SET ANSI_NULLS ON

SET QUOTED_IDENTIFIER ON

CREATE TABLE [dbo].[Employee](
    [Id] [int] IDENTITY(1,1) NOT NULL,
    [FirstName] [nvarchar](50) NULL,
    [Age] [tinyint] NULL,
    [Salary] [money] NULL,
 CONSTRAINT [PK_Employee] PRIMARY KEY CLUSTERED 
(
    [Id] ASC
)WITH (PAD_INDEX  = OFF, STATISTICS_NORECOMPUTE  = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS  = ON, ALLOW_PAGE_LOCKS  = ON) ON [PRIMARY]
) ON [PRIMARY]

This is the same SQL script that is used automatically (if enabled) when the demo server is run .

You also need to validate the connection string in the app.config file under ES2009WCF_Server. By default it points to the server ".\SQLExpress".

Creating The Employee EntitySpaces Objects

The first thing that was done when creating this demo was the creation of an Employee database table and the EntitySpaces objects that work with it. The Employee schema is described previously (see Pre-Setup). The EntitySpaces objects were placed in a shared library that contains all business objects that can be used both on the server and in a full (EntitySpaces-referencing) client. This is database-secure because a client does not have a database connection string in the generated code nor in its config file, it only has WCF references if so architected.

To generate EntitySpaces objects,

  1. Open the EntitySpaces generator by selecting Tools -> EntitySpaces in Visual Studio.
  2. In the Settings tab, click Configure Connection and point the generator to the Employee database. For this demo, the following was used:
    • Server: .\SQLExpress
    • Security: Integrated Security
    • Database: ES2009WCFDemo
  3. In the Templates tab, expand Templates->EntitySpaces->2009->C# and then select Generated - Classes Master (C#)
  4. Click the green Execute button.
  5. In the dialog that comes up, under Select the Output Path enter the file path to the shared library project that will be used to keep EntitySpaces business objects.
  6. The Namespace should be the namespace for your shared library.
  7. The Connection Name should be the name that will be used on your server to identify the connection string.
  8. The Tables or Views and Select Tables will be automatically selected as Tables and Employee, respectively.
  9. Click into the Proxy/Stub tab. Check the Generate the Proxy/Stub option as well as Support WCF.
  10. You should also specify a custom DataContract URI.
  11. When you click on OK, the files will be generated in the Output Path you specified.
  12. Go to Visual Studio's Solution Explorer, click on the shared library project, and then click the Solution Explorer toolbar button called "Show All Files". You should see the Generated folder that EntitySpaces created. Right-click on it and choose "Include".

When using lightweight proxies/stubs, will need to run the generator again for the client project to create special lightweight proxies/stubs. Remember that lightweight proxies/stubs are used primarily if your shared library, as well as EntitySpaces' runtime libraries, will not be referenced by the client application. So in this case, the client will need generated stubs.

So to create the lightweight proxies/stubs for the client, follow the same steps as for creating the "Classes Master" objects, except:

  1. Instead of using the template Generated - Classes Master (C#), expand ProxyStub and select Client Side Proxy/Stub
  2. In the field Select the Output Path, enter the path to your client app project instead of the shared library which will not be referenced in your client app.

Creating The WCF Server

The WCF Server in this demo (project ES2009WCF_Server) is just a console application with ServiceHost. You can also host WCF services in IIS 7 or with WAS (Windows Activation Services) but that is beyond the scope of this demo; again, WCF education is not the intent with this demo but rather how EntitySpaces can work in a WCF architecture.

Initializing EntitySpaces For The WCF Server

Before doing anything with EntitySpaces within a server application, an app.config file needs to be created.

  1. Right-click the server app project in Solution Explorer and select Add Item...
  2. Select Application Configuration file. (Retain the default filename, app.config.)
  3. When the file is added to the project, click on the file in Solution Explorer, then under Properties set Copy to Output Directory to Copy if newer. Note: Visual Studio automatically renames this file to %assemblyname%.config in the output directory when the project is built.

After setting up the app.config file with EntitySpaces settings, the first thing our server app needs to do in order to work with EntitySpaces and with the database is initialize EntitySpaces with:

esProviderFactory.Factory 
    = new EntitySpaces.LoaderMT.esDataProviderFactory();

About The XmlSerialized<T> and BinarySerialized<T> Wrappers

Before moving on, it should be noted that there are a few scenarios where manual serialization must be used when working with EntitySpaces over WCF. While EntitySpaces business objects can be generated with WCF compliance, EntitySpaces was not built around WCF (WCF is a relatively young technology, and Visual Studio's and .NET SDK's generation of WCF stubs is not fully evolved to handle all scenarios). For example, the manual serialization is necessary to retain the behavioral functionality of the EntitySpaces objects such as change/dirtiness state on the client in the conformance pattern used by EntitySpaces.

Examples of manual serialization for WCF have been posted in the EntitySpaces forums and blog, namely

  1. here: EntitySpaces WebServices Example Application (with WCF implications)
  2. and here: Pure WCF Client Side Proxies

The samples provided prompted the creation of a pair of serialization wrappers that I, the creator of this demo, decided to produce both for this demo and for future use anywhere manual serialization/deserialization is needed.

I posted the wrappers and documented them on my own blog:

Jon Davis: XmlSerialized<T> and BinarySerialized<T>

These wrappers are used extensively throughout this demo, primarily:

  • BinarySerialized<T>, utilized for exposing the Query object over WCF for full proxy clients.
  • XmlSerialized<T>, utilized for exposing all lightweight proxies/stubs for the lightweight clients that do not reference EntitySpaces.

Creating The Full & Lightweight Proxy Services

To create a WCF service that exposes API points for clients, Visual Studio's WCF Service template items were used:

  1. Right-click on the server project in Solution Explorer and select Add -> New Item...
  2. Select WCF Service and give it an appropriate name.
  3. In the generated interface file (the file prefixed with an 'I'), replace the DoWork() method interface declaration with the methods that are appropriate for your service. (Don't forget to mark each method with the [OperationContract] attribute.)
  4. In the generated class file, just right-click on the interface name where the class name is declared, and select "Implement interface". You may want to remove the #region markers to keep it clean.
  5. The generated method stubs should look like the ones illustrated in the ES2009WCF_Server project, under the Full and Light directories.
    • The Full directory demonstrates a service that would be used for clients that can reference EntitySpaces runtime libraries and would therefore also reference a shared library that is referenced by both client and server.
    • The Light directory demonstrates a service that would be used for clients that do not reference EntitySpaces runtime libraries. These clients would need the lightweight proxies/stubs to be generated specifically for the client. For more information, see the earlier section Creating The Employee EntitySpaces Objects.

About The Server Demo Tests

Some simple tests were added to the ES2009WCF_Server project while creating the server just to make sure things are working. This isn't a TDD implementation but basic invocation of some of the services' API is demonstrated.

The Console-Based Full Proxy Demo Client

This client app will automatically start the WCF Demo Service.

The first client that was created for this demo was the Console-Based Full Proxy Client. This is just a console application that invokes some of the WCF API points. It was created to test and make sure that the WCF services were working correctly. The net result is a demonstration of code that illustrates how EntitySpaces can interact with a WCF service using full proxies.

The verbiage of "full proxies" used here means that the client has EntitySpaces runtime libraries referenced, as well as a shared library that contains the business objects used on the server. The client sees these objects in the same way as the server sees these objects. The only difference is that the client cannot invoke the database directly through the EntitySpaces API. Instead, WCF must be used to explicitly manage all queries using the API points established by the server's WCF services.

Note that the "full proxy" implementation partially supports binary serialization of Query objects so that you can perform a filtered query from a client over WCF. This is partially demonstrated in the demo app by filtering on the Employee's FirstName property.

The Console-Based Lightweight Proxy Demo Client

This client app will automatically start the WCF Demo Service.

The Console-Based Lightweight Proxy Demo Client is a complete API demonstration of the WCF service that was exposed for lightweight proxies. It does not reference EntitySpaces runtime libraries nor any shared libraries except for core .NET libraries and the project that contains the Serialized utility classes discussed earlier.

Note that the special proxy/stub classes were generated for this client and added to the client project.

The WinForms-Based Full Proxy Demo Client

This client app will automatically start the WCF Demo Service.

The WinForms-Based Full Proxy Demo Client is a rich GUI illustration of how WCF can be used in a client/server application. It automatically loads all employees, allows you to edit the details of an employee, allows you to delete an employee, and allows you to create an employee. It also demonstrates the use of a binary-serialized Query object by displaying a filter form with a name parameter and range parameters for Age and Salary.

Coming Soon: The WPF-Based Lightweight Proxy Demo Client

We will be working on a WPF-based client that demonstrates the use of the lightweight proxy/stub classes to be released hopefully in the near future.

When EntitySpaces 2009 Q2 is released we will also have XML-serializable queries as well as a fresh new updated Silverlight demo that illustrates its use. This, too, will utilize the lightweight proxy/stub classes that unfortunately the ES 2008 Silverlight demo [1, 2] did not properly illustrate as the proxy/stub classes were not generated for it.

Closing Comments

Hopefully this sample solution clearly demonstrates how EntitySpaces can work with WCF without any significant hassle.

Jon Davis produced this demo as an outside consultant. He is currently employed as a C#/NET Developer for a very prominent Internet services provider, but offers evening/weekend consulting services for both software and web solutions. He retains a blog at http://www.jondavis.net/techblog/.
posted on Sunday, January 25, 2009 6:15:03 PM (Eastern Standard Time, UTC-05:00)  #    Comments [0]