Tuesday, August 21, 2007

The EntitySpaces persistence layer and business object architecture for Microsoft .NET now fully supports PostgreSQL 8.2. Using PostgreSQL on .NET has never been easier.

The EntitySpaces 2007 v0819 (beta) for PostgreSQL successfully passes our massive NUnit test suite including both the stored procedure and dynamic SQL modes. There is a new template that will generate your stored procedures if you desire to use stored procedures with your EntitySpaces PostgreSQL implementation.

See the Release Notes for more information on setup. You'll need the Npgsql .NET provider for PostgreSQL and MyGeneration. See our Home Page and grab the latest Trial version. It has the PostgreSQL support.

EntitySpaces

From mobile devices to large scale enterprise solutions in need of serious transaction support, EntitySpaces can meet your needs. Whether you’re writing an ASP.NET application with medium trust requirements, or a Windows.Forms application, the EntitySpaces architecture is there for you. EntitySpaces is provider independent, which means that you can run the same binary code against any of the supported databases. EntitySpaces is available in both C# and VB.NET. EntitySpaces uses no reflection, no XML files, and sports a tiny foot print of less than 200k. Pound for pound, EntitySpaces is one tough, dependable .NET architecture.

The EntitySpaces Team
--

EntitySpaces LLC
Persistence Layer and Business Objects for Microsoft .NET
http://www.entityspaces.net

posted on Tuesday, August 21, 2007 10:34:09 PM (Eastern Standard Time, UTC-05:00)  #   
 Saturday, July 28, 2007
We have written a webservices example using three different forms of the same service. These webservices allow you to retrieve and update data and are built upon the Microsoft SQL Northwind Employees table using EntitySpaces 2007.0.730.0 maintenance release which will be published this weekend (July 28th, 2007).  You can download both the WSConsumer application and the webservices (including source code) at the end of this article. The webservice is included so you can the see the source and run it locally if desired. The WSConsumer is setup to hit the services listed below on our site.

    Xml - http://www.entityspaces.net/webservices/csharp/ES_Xml.asmx

    XmlProxy - http://www.entityspaces.net/webservices/csharp/ES_XmlProxy.asmx

    Binary - http://www.entityspaces.net/webservices/csharp/ES_Binary.asmx

 

The Xml Webservice

The XML webservice is a basic SOAP example. It simply returns the Employees entity or the EmployeesCollection and everything is serialized accordingly. This type of webservice, the more traditional, doesn't require the webservice consumer to have any knowledge or link to any of your code.

[WebMethod]
public Employees GetEmployee(int i)
{
    Employees emp = new Employees();
    if (emp.LoadByPrimaryKey(i))
        return emp;
    else
        return null;
}

[WebMethod]
public EmployeesCollection GetAllEmployees()
{
    EmployeesCollection emps = new EmployeesCollection();
    if (emps.LoadAll())
        return emps;
    else
        return null;
}

Most people are familiar with traditional webservices. If you are interested in saving data through your webservice all the necessary code is in the demo app. However, security issues when allowing users to update data are not covered, those are left up to the developer to consider.

The XmlProxy Webservice (and WCF)

This is by far the most interesting and powerful example. The EntitySpaces proxy classes can be used in webservice scenarios in which you have control over both the webservice and the consumer as this example requires the proxy to be on both sides of the equation. Additionally, the EntitySpaces proxy classes are perfect for use as your WCF wire format. When we generated the proxy classes for the demo we did not check the "Support WCF" checkbox. We only generated the proxy portion which can be used on it's own without WCF. Some of the features of the proxy classes are follows:

  • Perfect for WCF communications.
  • Very easy to use wrappers
  • Very lightweight format which can serialize only the dirty rows and dirty columns.
  • Manages Added, Modified, and Deleted state for you.
  • Transparent Save logic.

If you're using EntitySpaces in WCF scenarios you can glean a lot from this section, it's shows exactly how your WCF packets will look. In this sample we need to manually serialize them into string form but in WCF scenarios you would just return the actual proxy's in your methods and the serialization is done for you. Take a look at our GetEmployee() method and notice the serialization so that we can return a raw string. Notice how we use the Proxy to wrap the real Employees object.

[WebMethod]
public string GetEmployee(int i)
{
    Employees emp = new Employees();
    if (emp.LoadByPrimaryKey(i))
    {
        // The Generated Proxy class
        EmployeesProxyStub proxy = new EmployeesProxyStub(emp);

        // Manually Serialize into string form (we want to deserialize it on the other side)
        XmlSerializer sf = new XmlSerializer(typeof(EmployeesProxyStub));
        StringWriter sw = new StringWriter();
        sf.Serialize(sw, proxy);

        return sw.ToString();
    }
    else
        return null;
}

 

The output of our call to the GetEmployee() method above can be seen below.

<?xml version="1.0" encoding="utf-16"?>
    <EmployeesProxyStub xmlns:xsi="
" xmlns:xsd="">
    <EmployeeID>1</EmployeeID>
    <LastName>Davolio</LastName>
    <FirstName>Jimmy</FirstName>
    <Title>Sales Representative</Title>
    <TitleOfCourtesy>Ms.</TitleOfCourtesy>
    <BirthDate>1948-12-08T00:00:00</BirthDate>
    <HireDate>1992-05-01T00:00:00</HireDate>
    <Address>507 - 20th Ave. E.Apt. 2A</Address>
    <City>Seattlesss</City>
    <Region>WA</Region>
    <PostalCode>78890</PostalCode>
    <Country>USA</Country>
    <HomePhone>(206) 555-9857</HomePhone>
    <Extension>989</Extension>
    <Notes>Some notes by Rick</Notes>
    <ReportsTo>161</ReportsTo>
   
<esRowState>Unchanged</esRowState>
</EmployeesProxyStub>

 

Notice the esRowState is "Unchanged". Now let's deserialize this in our client (in the demo the client is called WSConsumer). The code necessary to do this (taken from the WSConsumer application) is shown below.

// Call the XmlProxy Service
string data = wsProxyService.GetEmployee(1);

XmlSerializer xs = new XmlSerializer(typeof(BusinessObjects.EmployeesProxyStub));
StringReader sr = new StringReader(data);

// Deserialize into our Proxy
BusinessObjects.EmployeesProxyStub proxy =
xs.Deserialize(sr) as BusinessObjects.EmployeesProxyStub;

// Ask the proxy for the true Employees object
Employees emp = proxy.Entity;

Now let's modify the "emp" object we just deserialized and save it back through our service

emp.FirstName = "Joe";
emp.LastName = " EntitySpaces";

// True here means dirty columns only (primary keys are of course always sent)
BusinessObjects.EmployeesProxyStub proxy =
    new BusinessObjects.EmployeesProxyStub(this.emp, true);

XmlSerializer sf = new XmlSerializer(typeof(BusinessObjects.EmployeesProxyStub));
StringWriter sw = new StringWriter();
sf.Serialize(sw, proxy);

string packet = sw.ToString();

wsProxyService.SaveEmployee(packet);

Let's take a look at the packet sent back from the WSConsumer application to the webservice that was generated from the above code.

<?xml version="1.0" encoding="utf-16"?>
    <EmployeesProxyStub xmlns:xsi="
" xmlns:xsd="">
    <EmployeeID>1</EmployeeID>
    <LastName>EntitySpaces</LastName>
    <FirstName>Joe</FirstName> 
    <esRowState>Modified</esRowState>
</EmployeesProxyStub>

Notice that only the dirty columns are sent back and the esRowState is set to "Modified". We're almost at the end of this sequence, let's see how our XmlProxy webservice implements the SaveEmployee method.

[WebMethod]
public void SaveEmployee(string data)
{

    // Deserialize into our Proxy
    XmlSerializer xs = new XmlSerializer(typeof(EmployeesProxyStub));
    StringReader sr = new StringReader(data);

    EmployeesProxyStub proxy = xs.Deserialize(sr) as EmployeesProxyStub;

    // Ask for the real Employee entity
    Employees emp = proxy.entity;
    if (emp != null)
    {
        // Simply Save it, the added, modified, deleted state is 100% managed by the proxy
        emp.Save();
    }
}

Could it be any easier? Although not shown here (but demonstrated in the WSConsumer application) you can modify and transmit entire collections just as easily. The XmlProxy approach is the best way to go in all scenarios in which you are in control of both ends of the equation. Nothing could be easier or faster.

The Binary Webservice

The binary webservice approach can also be used in two way communication scenario's and while it is very easy to use, like the XmlProxy approach, it is far more bulky and bloated, however, the data is somewhat more secure in that it is not human readable.

[WebMethod]
public byte[] GetEmployee(int id)
{
    Employees obj = new Employees();
    if (obj.LoadByPrimaryKey(id))
    {
        BinaryFormatter bf = new BinaryFormatter();
        MemoryStream ms = new MemoryStream();
        bf.Serialize(ms, obj);

       return ms.ToArray();
    }
    else
        return null;
}

The packet transmitted will look something like this, only much larger.

AAEAAAD/////AQAAAAAAAAAMAgAAAD1CdXNPYmosIFZlcnNpb249MS4wLjAuMCwgQ3
VsdHVyZT1uZXV0cmFsLCBQdWJsaWNLZXlUb2tlbj1udWxsDAMAAABZRW50aXR5U3BhY2
VzLkNvcmUsIFZlcnNpb249MjAwNy4wLjczMC4wLCBDdWx0dXJlPW5ldXRyYWwsIFB1Ymxp
Y0tleVRva2VuPTFjMjY4MTk5ZmIyMWJmZTgMBAAAAElTeXN0ZW0sIFZlcnNpb249Mi4wLjA
uMCwgQ3VsdHVyZT1uZXV0cmFsLCBQdWJsaWNLZXlUb2tlbj1iNzdhNWM1NjE5MzRlMDg5D
AUAAABOU3lzdGVtLkRhdGEsIFZlcnNpb249Mi4wLjAuMCwgQ3VsdHVyZT1uZXV0cmFsLCBQ
dWJsaWNLZXlUb2tlbj1iNzdhNWM1NjE5MzRlMDg5BQEAAAAZQnVzaW5lc3NPYmplY3RzLkV
tcGxveWVlcw8AAAAfX0VtcGxveWVlc0NvbGxlY3Rpb25CeVJlcG9ydHNUbxpfVXBUb1RlcnJp
dG9yaWVzQ29sbGVjdGlvbh5fRW1wbG95ZWVUZXJyaXRvcmllc0NvbGxlY3Rpb24qX0VtcGxv
eWVlVGVycml0b3JpZXNDb2xsZWN0aW9uQnlFbXBsb3llZUlEHV9PcmRlcnNDb2xsZWN0aW9
uQnlFbXBsb3llZUlEBXF1ZXJ5GV9VcFRvRW1wbG95ZWVzQnlSZXBvcnRzVG8PbW9kaWZpZ
WRDb2x1bW5zA2Zrcxtlc0VtcGxveWVlcytQcm9wZXJ0eUNoY

And that is not all that is transmitted for a just a single employee object. The reason this is so large is that everything is serialized in binary serialization, the underlying DataTable, it's columns, rows, everything.

 

Summary

We encourage you to download and run our WebServices demo, it comes with the v2007.0730 Trial assemblies necessary to run the WSConsumer against our hosted webservices, and shows you the packets as they go back and forth (except in the case of the Xml service, there is no easy way to intercept the soap packets). There re some big improvements (though minor changes in code) in the v2007.0730 release that greatly improve the EntitySpaces proxy classes.

You can download the full source to both the WSConsumer and Webservices here ==> DOWNLOAD

NOTE: There is an enforced two second delay between requests to cut down on the traffic for these demo services.

EntitySpaces

From mobile devices to large scale enterprise solutions in need of serious transaction support, EntitySpaces can meet your needs. Whether you’re writing an ASP.NET application with medium trust requirements, or a Windows.Forms application, the EntitySpaces architecture is there for you. EntitySpaces is provider independent, which means that you can run the same binary code against any of the supported databases. EntitySpaces is available in both C# and VB.NET. EntitySpaces uses no reflection, no XML files, and sports a tiny foot print of less than 200k. Pound for pound, EntitySpaces is one tough, dependable .NET architecture.

The EntitySpaces Team
--

EntitySpaces LLC
Persistence Layer and Business Objects for Microsoft .NET
http://www.entityspaces.net

posted on Saturday, July 28, 2007 11:08:59 AM (Eastern Standard Time, UTC-05:00)  #   
 Saturday, July 14, 2007

Some of our exploratory work for EntitySpaces 2008 has led us to consider releasing our own pure ASP.NET code generation system, after all, ASP.NET pages are basically templates in that they allow you to toggle in and out of literal content and C# or VB.NET code. We have a prototype of this working already in-house. The UI in the prototype shown below is real and is served up via MyMeta of MyGeneration. The master template also calls a series of sub-templates to generate the mock EntitySpaces classes.

If you are an EntitySpaces fan you will recognize this screen, however, it is now a web page. The "Generate" button executes any number of sub-templates implemented as user controls or ASCX files. Sub-templates are quite simple to implement. Here is a sample of our mock esEntity.ascx page. 


<%@ Control Language="C#" AutoEventWireup="true"%>
<%@ Import Namespace = "MyMeta" %>

<%
//-----------------------------------------------------
// Gotta love it, full intellisense and you can debug
// your templates like a normal web site
//-----------------------------------------------------

MyMeta.dbRoot MyMeta = (MyMeta.dbRoot)this.input["MyMeta"];
table = (ITable)this.input["ITable"];
%>
public class <%=table.Name%>
{
<%foreach (IColumn col in table.Columns) {%>
public <%=col.LanguageType%> <%=col.Name%> { get; set; } <%}%>
}


This generates a simple mock class.

public class Categories
{
    public int CategoryID { get; set; }
    public string CategoryName { get; set; }
    public string Description { get; set; }
    public byte[] Picture { get; set; }
}

There are some real advantages to this approach. The first major advantage to this approach is the built in Intellisense both for MyMeta and for all of your other .NET namespaces as well. The second advantage is the ease of debugging. All you need to do is click the green arrow while in Visual Studio or Visual Web Developer 2005 Express Edition and you're debugging. You do not need to have IIS installed on your machine to use it either. Finally, you could even host this new code generation system on a server on your network and all of your development team could access it there.

EntitySpaces LLC is soon going to be opening up to facilitate 3rd party enhancements. We are going to be publishing the source code for one of our data providers as an example. This will allow 3rd party's to create data providers for database systems not currently supported by EntitySpaces, we will also supply guidelines for direction as well. We are also going to be opening up a template sharing area that will allow our customers to publish templates for the EntitySpaces architecture.

This new ASP.NET generation system (as yet unnamed) would also make it very easy for EntitySpaces developers to tweak templates and create and publish their own thus helping foster a wider reaching community. We really like the idea of this ASP.NET generator, it's so easy to use and debug. However, we need your feedback, please post your comments on this Thread in our forums.

EntitySpaces

From mobile devices to large scale enterprise solutions in need of serious transaction support, EntitySpaces can meet your needs. Whether you’re writing an ASP.NET application with medium trust requirements, or a Windows.Forms application, the EntitySpaces architecture is there for you. EntitySpaces is provider independent, which means that you can run the same binary code against any of the supported databases. EntitySpaces is available in both C# and VB.NET. EntitySpaces uses no reflection, no XML files, and sports a tiny foot print of less than 200k. Pound for pound, EntitySpaces is one tough, dependable .NET architecture.

The EntitySpaces Team
--

EntitySpaces LLC
Persistence Layer and Business Objects for Microsoft .NET
http://www.entityspaces.net

posted on Saturday, July 14, 2007 9:59:39 PM (Eastern Standard Time, UTC-05:00)  #   
 Tuesday, July 10, 2007

This is a little off topic but since we do run Google ads I thought I'd share this with the community. There is a report that you can run once you have signed into your Google Ad Account called the "Placement Report". I think this is a new report and it will shed some interesting light on the subject of who is clicking on your ads. When you run Google ads you can camp on keywords and optionally choose to have your ads run in Google's Content Network, here's how they describe it.

"Opting in to the content network allows your ad to appear on relevant sites that have actual content relating to your ad. Such contextual advertising is an easy way to reach your targeted audience from across the Web."

So now, let's look at where our EntitySpaces ads are showing (remember, we make a Persistence Layer for the .NET Framework).

googleads.PNG

We took a look at some of these sites; none of them are technical in the remotest since of the word. The two peggysim's sites on the list which generated 120+ clicks are barbie doll like sites? Most of them are basically "junk" sites, including myspace and others not even shown in the screen capture above.

Needless to say, we suspended all of our ads from running within the Google Content Network and we did fire off an email to their support staff and we will let you know what they say. However, the bulk of our advertising $$ was being spent on clicks received on these sites? Are these sites purposely hosting ads and clicking on them to make revenue? I am personally a big fan of Google and look forward to their response, however, if this problem is as big as I think it is there's a lot of money at stake.

At the very least Google should allow us to block certain websites in their content framework from being able to display our ads. If we suspect abuse by a particular site we should be allowed to block them.

[modified]

You can block certain sites, you will find this under Tools -> Site Exclusion so we will begin to re-enable and filter these sites that are clearly up to no good. Google should be shutting these sites down because these clicks are clearly staged. Run your reports folks and see where you clicks are coming from ....

EntitySpaces

From mobile devices to large scale enterprise solutions in need of serious transaction support, EntitySpaces can meet your needs. Whether you’re writing an ASP.NET application with medium trust requirements, or a Windows.Forms application, the EntitySpaces architecture is there for you. EntitySpaces is provider independent, which means that you can run the same binary code against any of the supported databases. EntitySpaces is available in both C# and VB.NET. EntitySpaces uses no reflection, no XML files, and sports a tiny foot print of less than 200k. Pound for pound, EntitySpaces is one tough, dependable .NET architecture.

The EntitySpaces Team
--

EntitySpaces LLC
Persistence Layer and Business Objects for Microsoft .NET
http://www.entityspaces.net

posted on Tuesday, July 10, 2007 8:41:50 AM (Eastern Standard Time, UTC-05:00)  #   
 Sunday, July 08, 2007

Our Trial Version is available for those looking for a great architecture for .NET. Also, for customers, EntitySpaces Developer is available as well as the source code, if you have purchased that.

New Installs: The latest MyGeneration (1.2.0.7 or higher) should be installed first, and then closed, before installing EntitySpaces Developer or Trial.

  1. You can download MyGeneration 1.2.0.7 HERE
  2. The updated VistaDB 3.0 MyMeta plugin for MyGeneration can be found HERE. Simply unzip into your MyGeneration folder.

EntitySpaces 2007 is a full install. You do not need an earlier version installed. To generate against MySQL, MyGeneration requires that MySql.Data.dll be copied to the MyGeneration Program Folder. After installing, please see the "Getting Started" PDF that is added to your EntitySpaces Start Menu folder.

Below are the release notes for EntitySpaces 2007.0.0709:

  • Added new "Proxy/Stub" tab to generated master templates.
  • Added support for Windows Communication Foundation (WCF) Databinding.
  • Upgraded to VistaDB Build 30.
  • Made the List<> operator implicit/widening for Collections.
  • Added Ignore Schema/Catalog checkboxes to MetadataMap template.
  • Added ability to set connection on esUtility.
  • Added esUtility to the EntitySpaces.Core.CE project.
  • Added new method to esEntityCollection named CreateColumnsForBinding() which can be called when a collection contains no data before data binding.
  • Enhanced Oracle Stored Procedure Templates - Concurrency Update/Delete. You need to regenerate Oracle stored procedures, and run the updated scripts.
  • Enhanced INotifyPropertyChanged logic to support WPF/XAML binding.
  • Fixed parameter issue with LoadDataSet.
  • Added [CLSCompliant(false)] to those variables that aren't compliant to get rid of warnings (just a naming convention thing).
  • Improved performance of string property settors.
  • Fixed parameter issue for SqlCe Float data type.
  • EntitySpaces Developer install now includes EntitySpacesDemo and VistaDB Compact Framework Demo. The \Runtime folder is not included. Just change the references so they point to your \Redistributables, or \Redistributables\Ce folder.
  • Fixed issue in Combine method for empty collections.
  • Fixed issue for Sql Server dynamic inserts for tables that have both an identity key column and a uniqueidentifier default newid() column.
  • Fixed issue with LoadByPrimaryKey parameter name for primary key columns with spaces in the name.

EntitySpaces

From mobile devices to large scale enterprise solutions in need of serious transaction support, EntitySpaces can meet your needs. Whether you’re writing an ASP.NET application with medium trust requirements, or a Windows.Forms application, the EntitySpaces architecture is there for you. EntitySpaces is provider independent, which means that you can run the same binary code against any of the supported databases. EntitySpaces is available in both C# and VB.NET. EntitySpaces uses no reflection, no XML files, and sports a tiny foot print of less than 200k. Pound for pound, EntitySpaces is one tough, dependable .NET architecture.

The EntitySpaces Team
--

EntitySpaces LLC
Persistence Layer and Business Objects for Microsoft .NET
http://www.entityspaces.net


kick it on DotNetKicks.com
posted on Sunday, July 08, 2007 8:54:58 PM (Eastern Standard Time, UTC-05:00)  #   
 Monday, June 18, 2007

MyGeneration is now an open source project under the BSD license on SourceForge.net, you can find the project HERE. This is not the end, but a new beginning for MyGeneration. You can easily sync up and compile MyGeneration right out of the box. You will most likely just need to remove the MyMetaVistaDB3xPlugin project unless you happen to have VistaDB on your system.

I created a folder called C:\MyGen and mapped my TortoiseSVN to https://mygeneration.svn.sourceforge.net/svnroot/mygeneration and did a full sync. Using this example you will find the overall solution here C:\MyGen\trunk\mygeneration\Zeus.sln.

Again, you can find the MyGeneration project on SourceForget.net HERE

 

posted on Monday, June 18, 2007 10:40:08 AM (Eastern Standard Time, UTC-05:00)  #   
 Thursday, June 14, 2007

Epoxy is a REST/POX webservice API that extends the EntitySpaces Architecture. If you are unfamiliar with what REST/POX is I would recommend checking out the excellent series over at Softies On Rails. This addition is meant to empower the creation of massively public http API's for any application that you develop with the EntitySpaces Architecture. Why would you want to expose your EntitySpaces objects via REST/POX and not just provide the defacto SOAP service API? Well, lets face it not everyone is living in the .NET world. Don't you want all your cool ruby coding friends to be able to consume your services easily? Of course you do, not to mention the 100's of other geeks that will write clients if only you allow them to do it in the language of their choice without jumping through a lot of hoops. For a more authoritative answer on when to use REST/POX instead of or in conjunction with SOAP, check out what Don Box has to say about it.

So now that we all agree that this is indeed something very useful, lets get down to implementation. We chose to use the new WCF REST/POX facilities to create our services. Below is a sample of our Service Contract

[ServiceContract]
public interface IUniversalContract
{
    [OperationContract(Action = "*", ReplyAction = "*")]
    Message ProcessMessage(Message input);
}

As you can see our interface consists of one Operation Contract which simply takes a Message as an input. The implementation of the interface is where the rubber hits the road. Below is a sample implementation of the above defined interface using the Employees class generated from the Northwind sample database.

public Message ProcessMessage(Message request)
{
    Message response = null;

    //The HTTP Method (e.g. GET) from the incoming HTTP request
    //can be found on the HttpRequestMessageProperty. The MessageProperty
    //is added by the HTTP Transport when the message is received.
    HttpRequestMessageProperty requestProperties =
        (HttpRequestMessageProperty)request.Properties[HttpRequestMessageProperty.Name];

    //Here we dispatch to different internal implementation methods
    //based on the incoming HTTP verb.
    if (requestProperties != null)
    {
        if (String.Equals("GET", requestProperties.Method,
            StringComparison.OrdinalIgnoreCase))
        {
            response = GetEmployee(request);
        }
        else if (String.Equals("PUT", requestProperties.Method,
            StringComparison.OrdinalIgnoreCase))
        {
            response = UpdateEmployee(request);
        }
        else if (String.Equals("POST", requestProperties.Method,
            StringComparison.OrdinalIgnoreCase))
        {
            response = AddEmployee(request);
        }
        else if (String.Equals("DELETE", requestProperties.Method,
            StringComparison.OrdinalIgnoreCase))
        {
            response = DeleteEmployee(request);
        }
        else
        {
            //This service doesn't implement handlers for other HTTP verbs (such as HEAD), so we
            //construct a response message and use the HttpResponseMessageProperty to
            //set the HTTP status code to 405 (Method Not Allowed) which indicates the client
            //used an HTTP verb not supported by the server.
            response = Message.CreateMessage(MessageVersion.None, String.Empty, String.Empty);

            HttpResponseMessageProperty responseProperty = new HttpResponseMessageProperty();
            responseProperty.StatusCode = HttpStatusCode.MethodNotAllowed;

            response.Properties.Add( HttpResponseMessageProperty.Name, responseProperty );
        }
    }
    else
    {
        throw new InvalidOperationException( "This service requires the HTTP transport" );
    }

    return response;
}

As you can see the above maps various http verbs to our CRUD methods for our objects. Using the new EntitySpaces WCF support the WCF serialization worked like a charm.

Endpoints are very important in a REST'ful API, so its worth covering briefly how the WCF implementation handles this. For the context of this post my virtual directory locally is ServiceHost. The actual service file will be called employee.svc in this sample. This relates directly to the address you will use to interact with the API over HTTP.

**Note if you want this to work you must have WCF installed, be using EntitySpaces Developer 0614 or higher and configure IIS for WCF REST/POX operations.

In our sample to get a list of all employees you would hit

http://localhost/servicehost/employees.svc/employees/

this would produce the following XML

<ArrayOfanyURI xmlns="http://schemas.microsoft.com/2003/10/Serialization/Arrays"
    xmlns:i="http://www.w3.org/2001/XMLSchema-instance">
    <anyURI>http://scattorshot/servicehost/employees.svc/employees/1</anyURI>
    <anyURI>http://scattorshot/servicehost/employees.svc/employees/2</anyURI>
    <anyURI>http://scattorshot/servicehost/employees.svc/employees/3</anyURI>
</ArrayOfanyURI>

As you can see it provides you with a list or URI's for each employee in the list. You can also perform an HTTP POST to this address to add a new employee. You may retrieve a single employee with an EmployeeID of 1 by performing an HTTP GET to the below address

http://localhost/servicehost/employees.svc/employees/1

this would produce the following XML

<Employees>
    <EmployeeID>1</EmployeeID>
    <LastName>Davolio</LastName>
    <FirstName>Nancy</FirstName>
    <Title>Sales Representative</Title>
    <TitleOfCourtesy>Ms.</TitleOfCourtesy>
    <BirthDate>1948-12-08T00:00:00</BirthDate>
    <HireDate>1992-05-01T00:00:00</HireDate>
    <Address>507 - 20th Ave. E. Apt. 2A</Address>
    <City>Seattle</City>
    <Region>WA</Region>
    <PostalCode>98122</PostalCode>
    <Country>USA</Country>
    <HomePhone>(206) 555-9857</HomePhone>
    <Extension>5467</Extension>
    <Photo>
        FRwvAAIAAn....the long base64 encoded string
    </Photo>
    <Notes>
        Education includes a BA in psychology from Colorado State University in 1970. 
        She also completed "The Art of the Cold Call."  Nancy is a member of Toastmasters International.
    </Notes>
    <ReportsTo>2</ReportsTo>
    <PhotoPath>http://accweb/emmployees/davolio.bmp</PhotoPath>
    <esRowState>Unchanged</esRowState>
</Employees>

After performing the HTTP GET and retrieving the desired employee resource you could modify it, and then perform an HTTP PUT to the same endpoint to update the employee. In order to delete an employee you would perform an HTTP DELETE to the above address to delete the resource. This is how your endpoints relate to your HTTP verbs, and is at the very heart of the REST style architecture.

So now you not only have the option to expose your EntitySpaces objects via SOAP services but REST/POX as well. We will be providing the full source code for the sample services as well as a small Windows Form client to consume the service. Choice is always a good thing, and this is certainly no exception.

EntitySpaces

From mobile devices to large scale enterprise solutions in need of serious transaction support, EntitySpaces can meet your needs. Whether you’re writing an ASP.NET application with medium trust requirements, or a Windows.Forms application, the EntitySpaces architecture is there for you. EntitySpaces is provider independent, which means that you can run the same binary code against any of the supported databases.EntitySpaces is available in both C# and VB.NET. EntitySpaces uses no reflection, no XML files, and sports a tiny foot print of less than 200k. Pound for pound, EntitySpaces is one tough, dependable .NET architecture.

The EntitySpaces Team
--

EntitySpaces LLC
Persistence Layer and Business Objects for Microsoft .NET
http://www.entityspaces.net

EntitySpaces.RestPox.zip (93.44 KB)
posted on Thursday, June 14, 2007 8:29:15 PM (Eastern Standard Time, UTC-05:00)  #   
EntitySpaces.RestPox.zip (93.44 KB)
 Saturday, June 09, 2007

The Windows Communication Foundation (WCF) has some interesting challenges when it comes to serialization. The model chosen by Microsoft does not work out-of-the-box and doesn't obey attributes such as [XmlIgnore] and alike. So, while you're classes might serialize perfectly in SOAP scenarios you'll be scratching your head when it comes to WCF serialization (in most cases). Of course, EntitySpaces supports binary serialization and you can certainly very easily use our binary serialization for WCF remoting when you are in control of both the client and server.

EntitySpaces is sporting a new tab on the "Generated Master" template in our upcoming ES2007 maintenance release. This release will most likely arrive on June 23rd, however, an internal beta will be provided for those doing WCF now, no public beta will be posted. If you are interested in working with our WCF support please email us support@entityspaces.net

So, if you are doing WCF programming this new release is definitely for you. 

 


Using the Employees table from Microsoft's Northwind database let's take a look at how to use the EntitySpaces WCF proxy stub classes. You can use the same proxy stub class on both the server and the client side. The proxy stub classes will automatically be placed in your generated "single file" during the code generation process. Two class will be created:

  1. EmployeesProxyStub
  2. EmployeesCollectionProxyStub

These are both lightweight intelligent wrappers that cause your EntitySpaces objects to be serialized correctly when used in WCF communications scenarios. This post is only going to cover the EmployeesProxyStub class, the EmployeesCollectionProxyStub will be covered in a follow up post. However, the collection proxy stub code has already been written and tested.

The EmployeesProxyStub

This is the wrapper for your single entity classes. You can use the proxy stub class to return data from the server to the client simply by executing this code.

 

public EmployeesProxyStub SomeMethod(int id)
{
    Employees employee = new Employees();
    employee.LoadByPrimaryKey(id);
    return new EmployeesProxyStub(employee);
}

 

The XML will look something like this. Notice that only the non-null columns are returned. This is because we checked the "EmitDefaultValue=False" checkbox on the template, otherwise there would have been place holder elements in the XML for those columns that were null.

 

<Employees xmlns="http://tempuri.org/" xmlns:i="http://www.w3.org/2001/XMLSchema-instance">
    <EmployeeID>257</EmployeeID>
    <LastName>Goo</LastName>
    <FirstName>foo</FirstName>
    <esRowState>Unchanged</esRowState>
</Employees>

 

This is an example of the generated proxy stub class. 

 

[DataContract(Namespace = "http://tempuri.org/", Name = "Employees")]
[Serializable]
public class EmployeesProxyStub
{
    public EmployeesProxyStub(Employees obj)
    {
        this.entity = obj;
    }

    [DataMember(Order = 1, EmitDefaultValue = false)]  // EmitDefaultValue -> see checkbox above
    public System.Int32? EmployeeID
    {
        get
        {
            if (this.Entity.es.IsDeleted)
                return (System.Int32?)this.Entity.
                    GetOriginalColumnValue(EmployeesMetadata.PropertyNames.EmployeeID);
            else
                return this.Entity.EmployeeID;
        }
       set { this.Entity.EmployeeID = value; }
    }

    [DataMember(Order = 2, EmitDefaultValue = false)]  // EmitDefaultValue -> see checkbox above
    public System.String FirstName
    {
        get
        {
            if (this.Entity.es.IsDeleted)
                return null;
            else
                return this.Entity.FirstName;
        }
        set { this.Entity.FirstName = value; }
    }

    // and more properties are in here ....

    [DataMember(Order=19)]
    public string esRowState  // Present only if "Include Added/Modified/Deleted" is clicked
    {
        get
        {
            return this.Entity.es.RowState.ToString();
        }

        set
        {
            switch (value)
            {
                case "Unchanged":
                    this.Entity.AcceptChanges();
                    break;

                case "Added":
                    break;

                case "Modified":
                    this.Entity.AcceptChanges();
                    this.Entity.es.RowState = DataRowState.Modified;
                    break;

                case "Deleted":
                    this.Entity.AcceptChanges();
                    this.Entity.MarkAsDeleted();
                    break;
            }
        }
    }

    public Employees Entity
    {
        get
        {
            if (this.entity == null)
            {
                this.entity = new Employees();
            }

            return entity;
        }

        set
        {
            this.entity = value;
        }
    }

    [NonSerialized]
    public Employees entity;

}

 

Now let's receive our Employees packet on the client, modify it, and send it back to the server.

 

EmployeesProxyStub proxy = call SomeMethod(); ...
Employees emp = proxy.Entity;  // grab the true Employees object now

emp.FirstName = "ES Rocks!";

call SendDataBackToClient(proxy);

 

The Server will now receive this XML packet. Notice that the esRowState is now Modified. The esRowState is interpreted in the set accessor of the proxy stub in the esRowState property to ensure that the entity is in the proper state after deserialization.

 

<Employees xmlns="http://tempuri.org/" xmlns:i="http://www.w3.org/2001/XMLSchema-instance">
    <EmployeeID>257</EmployeeID>
    <LastName>Goo</LastName>
    <FirstName>ES Rocks!</FirstName>
    <esRowState>Modified</esRowState>
</Employees>

 

On the server you would deserialize just as we did on the client and then call Save(). Very simple. We are thinking of adding another checkbox in the template so that the proxy stubb class will only send dirty columns back when modified. For Deleted records only the primary key(s) are sent with an esRowState value of Deleted. Again, you can simply call save, no MarkAsDeleted() call is necessary, it's already been done for you.

From mobile devices to large scale enterprise solutions in need of serious transaction support, EntitySpaces can meet your needs. Whether you’re writing an ASP.NET application with medium trust requirements, or a Windows.Forms application, the EntitySpaces architecture is there for you. EntitySpaces is provider independent, which means that you can run the same binary code against any of the supported databases.EntitySpaces is available in both C# and VB.NET. EntitySpaces uses no reflection, no XML files, and sports a tiny foot print of less than 200k. Pound for pound, EntitySpaces is one tough, dependable .NET architecture.

The EntitySpaces Team
--

EntitySpaces LLC
Persistence Layer and Business Objects for Microsoft .NET
http://www.entityspaces.net

posted on Saturday, June 09, 2007 11:20:47 AM (Eastern Standard Time, UTC-05:00)  #