Tuesday, March 02, 2010

Warning: A feeling of euphoric power coupled with feelings of invincibility have been noted by the EntitySpaces Development Team when using EntitySpaces 2010. This will be especially true for those customers using Silverlight and WCF together. The interaction between these technologies and EntitySpaces 2010 could prove to be more than some customers can handle. Please check with your IT staff to make sure this combination is safe for you.

Also, the performance increase in EntitySpaces 2010 is significant, customers are urged to throttle back and work their dosage up slowly to maximum as to not overwhelm their DBMS systems.

Finally, in more extreme cases developers have been seen ‘strutting’ down hallways trash talking wildly about how their product is going to destroy their competition. Other signs may include finishing tasks way ahead of schedule, begging team leads incessantly for more work to do, and working seven, dare we say, six hour days, and spending more time with their families.

If you recognize any of these symptoms don’t be alarmed, instead be sure to pat the developer on the back and say to them “Job well done”. If your competition is getting ahead and your company is still struggling you might try to find out if there development team is all hopped up on EntitySpaces. If they’re winning bid after bid and you’re losing out to them there is a good chance this is the case. The good news is you too have the same access to EntitySpaces, no prescription required.

Please, use EntitySpaces 2010 responsibly.

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, a Silverlight/WCF application, a Mono application, 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.

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

posted on Tuesday, March 02, 2010 11:10:38 AM (Eastern Standard Time, UTC-05:00)  #    Comments [0]
 Saturday, February 27, 2010
kick it on DotNetKicks.com     Shout it

We are very pleased to be able to show you some of the awesome power coming in EntitySpaces 2010. We think ES2010 provides unmatched power when it comes to working with Silverlight and WCF services. Not only do our smart proxies track row state but they also track column dirty state. You can now bring back extra columns that are fetched via joins (or derived columns) to the client . Probably one of the most awesome feature is the ability to bind to these extra columns under Silverlight. As far as we know we are the only architecture that allows you to do this. You can actually bind to properties for which you have no property accessors, think of it as ITypedList for Silverlight if you will.

video

PART ONE

This first video is key to understanding our WCF Serialization capabilities. We think you will be impressed. The XML is shown each step along the way from server to client and back again. We use our own wrapper for the DataContract serializer to make things easy to demo. We think once you see this you will begin to understand what we have accomplished. Don’t skip this video, it is key to able to understanding Part Two.

video

PART TWO

This second video shows everything in Part One working in a real WCF / Silverlight application. We even bind to the extra column brought back via our Dynamic Query. And this column is not a property in our strongly typed entity. However, be forewarned, we don’t show the mechanics behind this for competitive reasons, once we ship ES2010 it will be made known.

 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, a Silverlight/WCF application, a Mono application, 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.

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

posted on Saturday, February 27, 2010 3:52:18 PM (Eastern Standard Time, UTC-05:00)  #    Comments [0]
 Thursday, January 21, 2010
Now having looked at the video this morning I promise not to make a video at 1 in the morning when I can barely hold my head up. I'm buying a professional quality microphone and will make video's in the morning after a fresh cup of coffee, still, the proxies are very cool ...

This preview should really get you fired up for ES2010. Our proxies are now even smarter. In EntitySpaces 2009 (ES2009) our proxies track row state for you automatically which is cool, however in ES2010 they also track column level dirty information. The proxies can also be decorated with DataContract, XML, and JSon serialization attribute tags all at the same time. This is very cool for client side proxies as clients can then serialize the data to disk, or to the Browser, or simply change the data and send it back to the server.

Our client side proxies are also great candidates for MVC development. With the coming release of .NET 4.0 you will have WCF and Workflow (WF4) integration capabilities and our client side proxies will make great data envelopes for traveling around inside of WF4 and ensure that your row state and column level dirty information are always up-to-date. We are making sure EntitySpaces can go where ever you need to go and do so effortlessly, and this includes the Cloud (more on that in an upcoming preview).

Our next preview video will show you ES2010’s ability to generate your WCF endpoints automatically. You can generate all of your WCF end points for your data in one big “mombo” WCF Service or have each entity type housed in it’s own WCF Service. This EntitySpaces template is highly customizable as well since it does not generate the core classes. It merely creates WCF Services and you can tweak it to meet your specific needs. Also, we are adding an online sharable template library that is accessible from within the EntitySpaces Visual Studio AddIn. That means you can upload and download templates directly from the template browser. So, if you create a cool tweak to our WCF template or create an awesome REST template for EntitySpaces and you want to share it you can, and it will automatically show up in the EntitySpaces Template Browser for all EntitySpaces users. Are you excited yet?

Take a look at this preview and see what you think.

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, a Silverlight/WCF application, a Mono application, 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.

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

posted on Thursday, January 21, 2010 12:40:42 AM (Eastern Standard Time, UTC-05:00)  #    Comments [0]
 Sunday, December 06, 2009

This question has been brought up recently so we created a sample to demonstrate how this can be accomplished. When we refer to Virtual Properties we mean properties that you manually add to your Custom classes (as opposed those that are created from your database schema during code generation and wind up in your generated classes). In this example we are going to create two Virtual Properties, one that is backed by a private string variable and the other backed by a column in the underlying DataTable.

Adding the Virtual Properties to the Custom Class (Your Main Entity)

Notice the two properties MyCustomProperty and MyCustomPropertyFullName

namespace BusinessObjects
{
    public partial class Employees : esEmployees
    {
        // Virtual Property backed by a private string
        public string MyCustomProperty
        {
            get { return myCustomProperty; }
            set { myCustomProperty = value; }
        }
        private string myCustomProperty;

        // Virtual Property backed by a Column in the underlying DataTable
        public string MyCustomPropertyFullName
        {
            get { return this.GetSystemString("FullName"); }
            set { this.SetColumn("FullName", value, true); } // New Method
        }

        // Makes sure these properties show up when binding ...
        protected override List<esPropertyDescriptor> GetLocalBindingProperties()
        {
            List<esPropertyDescriptor> props = new List<esPropertyDescriptor>();

            props.Add(new esPropertyDescriptor(this, "MyCustomProperty", typeof(string)));
            props.Add(new esPropertyDescriptor(this, "MyCustomPropertyFullName", typeof(string)));

            return props;
        }

        // We need to do this for the deserialization process (more on this later)
        public override void AddNew()
        {

            // only needed if for the DataTable backed column
            base.AddNew();

            if (!this.Table.Columns.Contains("FullName"))
            {
                this.Table.Columns.Add("FullName", typeof(System.String));
            }
        }

    }
}

Typically, you don’t allow users edit virtual properties. In this example we are allowing it and this is the reason we needed to override AddNew. The reason we need to do this is that when we deserialize from the client back to the server you do not get to create the EmployeesCollection, instead the deserialization process does this. So, we overload AddNew() to make sure our underlying DataTable contains the DataColumn to hold our “FullName” value coming back from the client side. In ES2010 we are going to take a hard look at this and make this area easier. With all of the new emphasis on Silverlight 4.0 we want to make sure our proxies and serialization logic are the best and easiest they can be. However, if you are not going to allow users to edit “Virtual Properties” on the client there is no need to override AddNew.

The above code in “red” is new and will be the next maintenance release. The allows you to set virtual columns in the DataTable and not have them marked as dirty which causes the provider to try to save it. However, you can do this now without the new method though the code for that is not shown here.

Adding the Virtual Properties to the Proxies

The Server Side Proxy Class

When we generated the server and client proxies we made sure to check the “CompactXml” checkbox. This makes the XML sent over the wire much more compact. Our “Compact Xml” names each field a0, a1, a2 and so on (in the XML only). This makes the XML so much smaller than using the actual property names. However, it doesn’t effect your property names whatsoever, you still always work with your nice names in code. We recommend that you start your Virtual Properties at “a1000” and then you will never get into to trouble, that is, unless you have 1000 columns in your table in which case you probably have bigger problems.

Our server side and client side proxies are partial classes, so you can easily add more properties to them. Below is the server proxy partial class that we created to house our two addition properties. This ensures that you never hand edit the generated proxies.

namespace BusinessObjects
{
    public partial class EmployeesProxyStub
    {
        [DataMember(Name = "a1000", Order = 1000, EmitDefaultValue = false)]
        public System.String MyCustomProperty
        {
            get
            {
                return this.Entity.MyCustomProperty;
            }
            set { this.Entity.MyCustomProperty = value; }
        }

        [DataMember(Name = "a1001", Order = 1001, EmitDefaultValue = false)]
        public System.String MyCustomPropertyFullName
        {
            get
            {
                return this.Entity.MyCustomPropertyFullName;
            }
            set { this.Entity.MyCustomPropertyFullName = value; }
        }
    }
}

The Client Side Proxy Class

If you are deserializing from the server side proxies into the client side proxies you want to use the same signature for the the properties in the client side proxy.

namespace Proxies
{
    public partial class EmployeesProxyStub
    {
        [DataMember(Name = "a1000", Order = 1000, EmitDefaultValue = false)]
        public System.String MyCustomProperty
        {
            get
            {
                return _myCustomProperty;
            }
            set
            {
                this.SetDirty();
                this._myCustomProperty = value;
                this.RaisePropertyChanged("MyCustomProperty");
            }
        }
        private System.String _myCustomProperty;

        [DataMember(Name = "a1001", Order = 1001, EmitDefaultValue = false)]
        public System.String MyCustomPropertyFullName
        {
            get
            {
                return _myCustomPropertyFullName;
            }
            set
            {
                this.SetDirty();
                this._myCustomPropertyFullName = value;
                this.RaisePropertyChanged("MyCustomPropertyFullName");
            }
        }
        private System.String _myCustomPropertyFullName;
    }
}

One Minor Gotcha

The way our logic is setup the esRowState property of the proxies must be the last property serialized because it determines the row state. Therefore, what we did for this example was to hand edit both the generated proxies (server and client) and change the esRowState to the name and order of 10,000 to make sure it’s last. Here are the hand edits …

[DataMember(Name = "a10000", Order = 10000)]
public string esRowState
{
    get { return this._esRowState; }
    set { this._esRowState = value; }
}

However, we have already made changes in our template(s) so that our next maintenance release (due out very soon) will always set the esRowState to the name and order of 10,000. If you want to make these hand edits to your templates you can do so very easily and simply regenerate. You would need to do this in both proxy templates if you are using both the server and client proxies.

BEFORE

<%if(WcfSupport){%>[DataMember(Name="<%=CompactXML ? "a" + compactXmlIndex++.ToString() : "esRowState"%>"<%if(WcfOrder){%>, Order=<%=(++lastOrdinal).ToString()%><%}%>)]<%}%>
public string esRowState
{
    get { return TheRowState;  }
    set { TheRowState = value; }
}<%}%>

 

AFTER

<%if(WcfSupport){%>[DataMember(Name="<%=CompactXML ? "a10000" : "esRowState"%>"<%if(WcfOrder){%>, Order=10000<%}%>)]<%}%>
public string esRowState
{
    get { return TheRowState;  }
    set { TheRowState = value; }
}<%}%>

 

Finally, the test, does it work?

First, this code is for demonstration purposes only. You never have to use our esDataContractSerializer manually, in fact, you should not be using it unless you absolutely have to. Instead, just pass our proxies to and from your WCF methods as normal parameters and the serialization will happen normally. However, the code below uses our esDataContractSerializer so you can try this in your own code quickly without having to build the services and test it all. In this example we serialize from the server proxies (found in your generated classes) to the client side proxies and back again. If you were using the server proxies on both sides of the conversation you wouldn’t need to generate or mess with the client side proxies of course.

It’s fun to run the code below and look at the XML that is sent back and forth.

private void button1_Click(object sender, EventArgs e)
{
    try
    {
        EmployeesCollection coll = new EmployeesCollection();
        EmployeesQuery q = new EmployeesQuery("e");

        q.SelectAllExcept(q.Notes, q.Photo); // We want all columns but the Notes and Photo
        q.Select((q.LastName + ", " + q.FirstName).As("FullName"));  // Fills our DataTable backed property
        q.es.Top = 3;

        if (coll.Load(q))
        {

            // Change our string back properties
            foreach (Employees emp in coll)
            {
                emp.MyCustomProperty = "Test";
            }

            // Create Our Proxy Stubb
            BusinessObjects.EmployeesCollectionProxyStub server = new BusinessObjects.EmployeesCollectionProxyStub(coll, false);

            // Serialize it into a string and return this string to Silverlight
            string xml = esDataContractSerializer.ToXml(server);

            using (StreamWriter sw = File.CreateText("C:\\query.xml"))
            {
                sw.Write(xml);
                sw.Flush();
                sw.Close();
            }

            // Deserialize the string above into our Client side proxy
            Proxies.EmployeesCollectionProxyStub client = esDataContractSerializer.FromXml(xml, typeof(Proxies.EmployeesCollectionProxyStub))
                as Proxies.EmployeesCollectionProxyStub;

            // Set a property and notice that esRowState goes to Modified
            client.Collection[0].LastName = "CrazyDude";
            client.Collection[0].MyCustomProperty = "MyCustomProperty";
            client.Collection[0].MyCustomPropertyFullName = "Griffin, Mike";

            // Serialize our client side proxy into xml and send it to the server
            xml = esDataContractSerializer.ToXml(client);

            // Deserialize it on the server, the esRowState is modifed as we would expect
            BusinessObjects.EmployeesCollectionProxyStub server1 =
                esDataContractSerializer.FromXml(xml, typeof(BusinessObjects.EmployeesCollectionProxyStub))
                as BusinessObjects.EmployeesCollectionProxyStub;

            // Now save the Entity
            server1.GetCollection().Save();
        }
    }
    catch (Exception ex)
    {

    }
}

The XML

Notice that our two custom properties are at a1000, and a1001 and we have changed esRowState to be a10000.

<EmployeesCollection xmlns="http://tempuri.org/" xmlns:i="http://www.w3.org/2001/XMLSchema-instance">
    <Collection>
        <Employees>
          <a0>1</a0>
          <a1>CrazyDude</a1>
          <a2>AAAA</a2>
          <a3>Sales Representative</a3>
          <a4>Ms.</a4>
          <a5>1948-12-08T00:00:00</a5>
          <a6>1992-05-01T00:00:00</a6>
          <a8>Seattle</a8>
          <a9>WA</a9>
          <a10>78890</a10>
          <a11>USAa</a11>
          <a12>(206) 555-9857</a12>
          <a13>5467</a13>
          <a16>70272</a16>
          <a17>http://accweb/emmployees/davolio.bmp</a17>
          <a1000>Test</a1000>
          <a1001>CrazyDude, AAAA</a1001>
          <a10000>Unchanged</a10000>

        </Employees>
        <Employees>
          <a0>2</a0>
          <a1>Fuller</a1>
          <a2>tttt</a2>
          <a3>Vice President, Sales</a3>
          <a4>Ms.</a4>
          <a5>1953-02-19T00:00:00</a5>
          <a6>1992-08-14T00:08:00</a6>
          <a7>908 W. Capital Way</a7>
          <a8>Tacoma</a8>
          <a9>WA</a9>
          <a10>98401</a10>
          <a11>USA</a11>
          <a12>(206) 555-9482</a12>
          <a13>3457</a13>
          <a16>99</a16>
          <a17>http://accweb/emmployees/fuller.bmp</a17>
          <a1000>Test</a1000>
          <a1001>Fuller, tttt</a1001>
          <a10000>Unchanged</a10000>

        </Employees>
        <Employees>
          <a0>3</a0>
          <a1>Spaces</a1>
          <a2>tttt</a2>
          <a3>Sales Representative</a3>
          <a4>Ms.</a4>
          <a5>1963-08-30T00:00:00</a5>
          <a6>1992-04-01T00:00:00</a6>
          <a7>722 Moss Bay Blvd.</a7>
          <a8>Kirkland</a8>
          <a9>WA</a9>
          <a10>98032</a10>
          <a11>USA</a11>
          <a12>(206) 555-3412</a12>
          <a13>3355</a13>
          <a16>2</a16>
          <a17>http://accweb/emmployees/leverling.bmp</a17>
          <a1000>Test</a1000>
          <a1001>Spaces, tttt</a1001>
          <a10000>Unchanged</a10000>

        </Employees>
    </Collection>
</EmployeesCollection>

Summary

This was an extremely valuable exercise for us and revealed a few shortcomings when it comes to serialization virtual properties. Is is possible to implement your code without the new method in red above but that code is not shown here. We are hoping most of you desiring this functionality will be upgrading to our upcoming maintenance release. Also, remember, you can generate entities from views and in views you can create columns that are virtual and not based on database columns at all. This would make a lot of the above work a mute exercise with the caveat that views cannot be saved (easily) back to the database.

Our proxies are very important to future of EntitySpaces and they even run down inside the browser along with our DynamicQueries inside of Silverlight (under the browser) and we will be stepping back to see how we can make them far more powerful and easy to expand in ES2010. However, our next maintenance release will certainly make the above code a no brainer.

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, a Silverlight/WCF application, a Mono application, 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.

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

posted on Sunday, December 06, 2009 2:53:37 PM (Eastern Standard Time, UTC-05:00)  #    Comments [0]
 Sunday, September 27, 2009
kick it on DotNetKicks.com Shout it

We are pleased to make our Official EntitySpaces Q3 Release available. Both the Developer and Source code are available for download to current customers and the Trial version is the official ES2009 Q3 production release as well. The version number is 2009.2.0928.0. We recommend you download ES2009 Q3 saving it to disk and then install via the Start menu’s “Run As …” command and run as “Admin”. This is necessary for Windows Vista and Windows 7.

NOTE: You must regenerate your “Generated” classes and your stored procedures, if using stored procedures.

The EntitySpaces 2009 Q3 release has some of the best support for Silverlight and WCF that any ORM has to offer. Our smart proxies are very powerful and make working with WCF services and Silverlight a breeze. See the PDF’s in our Silverlight and WCF demos. Also, our DynamicQuery API is much more powerful in this release. Here is a quick list of features, fixes, and enhancements that are in this release.

The release notes can be found in this PDF file. There are some breaking changes with our 0209 Production Release which is unusual for us, however, they are pretty minor.

  • Sybase SQL Anywhere Support Including the Compact Framework
  • Excellent Silverlight and WCF Support
  • 64 bit runtime assemblies are included
  • A New EntitySpaces.DynamicQuery Assembly which is Silverlight Compliant
  • A New EntitySpaces Generic Concurrency Mechanism for all databases
  • DynamicQuery - The Having Clause is Now Supported
  • DynamicQuery - Full Expressions in OrderBy and GroupBy
  • DynamicQuery - Daisy Chaining Syntax has been fixed
  • DynamicQuery - Supports “Raw SQL” Everywhere
  • DynamicQuery - Sub Operator Ordering Fix
  • DynamicQuery - Order of Values More Flexible
  • DynamicQuery – Serializable in XML (very tiny packets)
  • DynamicQuery – Parse() method allows you to get the SQL without executing the statement
  • Major Proxy Stub Enhancements (WCF/WebServices/Silverlight) and Compact XML Mode
  • Enhanced UserData.xml file (support for multi dabase developers)
  • Editing User Metadata Easier through the .NET Property Grid
  • Connection Configuration Information Enhancements (no longer read only, catalog/schema added)
  • VistaDB and Microsoft SQL CE Password Bug Fixes
  • Microsoft SQL CE “TOP” syntax fixed
  • There is now a Twitter toolbar button on the “Whats New” tab
  • In the Settings “Other” tab you can control what double-click means for a template.
  • In the Settings “Other” tab you can turn off the DateTime stamp in the header.
  • Brand new Silverlight and WCF Demos
  • We are now bound to VistaDB 3.4.1.84

Of course, there are many other internal changes not listed in the above list.

One thing we didn’t get completed is “path relative project files”. We know this is a very important feature however it turned out be be more complicated than we first thought. However, this will be a high priority for 2010. Also, the Trial version comes with the source code to our Sybase plugin for our code generation engine which will allow you to easily switch Sybase versions. The ES2009 Q3 Developer does not have the Sybase source in it, we will make it available via a separate download.

We will be doing a series of blog posts highlighting a lot of these new features so stay tuned.

 

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, a Silverlight/WCF application, a Mono application, 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.

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

posted on Sunday, September 27, 2009 9:32:03 PM (Eastern Standard Time, UTC-05:00)  #    Comments [0]
 Thursday, July 16, 2009
kick it on DotNetKicks.com

We have pushed our EntitySpaces Silverlight application up so you can run it and take a look at it. We decided to compile it under the Silverlight 3 toolset so it requires Silverlight 3 to run it. We did this to make sure we are compatible. Silverlight 3 is RTM now and you can download the Visual Studio tools for it HERE but you do not need these to run the demo, just to develop Silverlight 3 applications. There is a lot of code posted in this blog post but we thought you might really want to know how this stuff works, it’s not that hard to understand if you take the time to look at the code. The online demo can be found here ==> DEMO

image

You can add rows and edit rows and then save the data. We are using the Microsoft SQL Northwind database, specifically the Employees table. When you search you can search on the first name or last name fields. The purpose of this demo is not to make a really cool Silverlight UI, but to show how easy it is to use EntitySpaces to write a Silverlight application. There is one glitch when editing data. You need to move off of the selected row for your edits to “take”. This is a Silverlight issue and not an EntitySpaces Issue. The demo is included in our current alpha, however the version shown here is fancier. (It will be in the next release as shown above).

The EntitySpaces Silverlight Demo uses our EntitySpaces proxies on both sides of the conversation. The client side proxies run under Silverlight and our server side proxies run on the server. The Silverlight application hits our WCF service to fetch the data.

The WCF Service

This is what the WCF Service looks like including the Interface. The Interface for the service is shown below. Notice we are returning and taking the EntitySpaces Proxy Stub classes as parameters. However, we pass the EntitySpaces DynamicQuery to the server in string form. The EntitySpaces DynamicQuery is now fully functional under Silverlight and requires only a single 49k assembly which will automatically download with your Siverlight application.

using System.ServiceModel;
 
using BusinessObjects;
 
namespace EntitySpaces.SilverlightApplication.Web
{
    [ServiceContract]
    public interface INorthwind
    {
        [OperationContract]
        EmployeesCollectionProxyStub GetEmployees(string employeesQuery);
 
        [OperationContract]
        EmployeesCollectionProxyStub SaveEmployees(EmployeesCollectionProxyStub collection);
    }
}
 
The implementation class is shown below. Notice in GetEmployees() we deserialize the incoming query (passed as a string) with a single one-line call into a full server side query that we can execute. We then use that query to load our collection, and finally wrap it with a proxy collection and return it. The Save() method is ridiculously simple and powerful. Notice that we merely access the incoming proxies “Collection” property (which is a full EmployeesCollection class) and call save on it. Then we simply return the very same proxy that was sent to us as the incoming parameter. Try clicking the Add button in our demo a few times and then press the Save button. Notice the auto identity columns are immediately reflected in the grid. These are returned automatically via our save method. This is an incredibly powerful and easy way to create Silverlight applications. The row state, including added, modified, and deleted, are automatically maintained for you. All you have to do is call save.
 
using System;
using System.Collections.Generic;
using System.ServiceModel.Activation;
 
using BusinessObjects;
 
namespace EntitySpaces.SilverlightApplication.Web
{
    [AspNetCompatibilityRequirements(RequirementsMode = AspNetCompatibilityRequirementsMode.Allowed)]
    public class Northwind : INorthwind
    {
        #region INorthwind Members
 
        public EmployeesCollectionProxyStub GetEmployees(string serializedQuery)
        {
            List<Type> types = new List<Type>();
            types.Add(typeof(EmployeesQuery));
 
            EmployeesQuery employeesQuery = EmployeesQuery.SerializeHelper.FromXml(
                serializedQuery, typeof(EmployeesQuery), types) as EmployeesQuery;
 
            EmployeesCollection employeesCollection = new EmployeesCollection();
            if (employeesCollection.Load(employeesQuery))
            {
                EmployeesCollectionProxyStub proxy = new EmployeesCollectionProxyStub(employeesCollection);
                return proxy;
            }
 
            return null;
        }
 
        public EmployeesCollectionProxyStub SaveEmployees(EmployeesCollectionProxyStub collection)
        {
            if (collection != null)
            {
                collection.GetCollection().Save();
                return collection;
            }
 
            return null;
        }
 
        #endregion
    }
}


The Silverlight Page

Our Page.xaml file looks like this. A lot of this is just noise like setting up the buttons and such. The part you are interested in is the <data:DataGrid.Columns> section where we manually setup the columns we want to display in the grid. We could have used AutoGenerateColumns=“True” however. For the two date columns we use a DataGridTemplateColumn in order to hookup the fancy date editing control. We also set the EmployeeID column to read only so that users cannot edit the primary key.

<UserControl xmlns:controls="clr-namespace:System.Windows.Controls;assembly=System.Windows.Controls"  xmlns:data="clr-namespace:System.Windows.Controls;assembly=System.Windows.Controls.Data"  x:Class="EntitySpaces.SilverlightApplication.Page"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
 
    <Grid Background="Black" >
 
        <Grid.RowDefinitions>
            <RowDefinition Height="50"></RowDefinition>
            <RowDefinition Height="*"></RowDefinition>
            <RowDefinition Height="50"></RowDefinition>
        </Grid.RowDefinitions>
 
        <Grid Grid.Row="0" Margin="7">
 
            <Grid.ColumnDefinitions>
                <ColumnDefinition Width="100"></ColumnDefinition>
                <ColumnDefinition Width="300"></ColumnDefinition>
                <ColumnDefinition Width="*"></ColumnDefinition>
                <ColumnDefinition Width="240"></ColumnDefinition>
                <ColumnDefinition Width="75"></ColumnDefinition>
            </Grid.ColumnDefinitions>
            
            <HyperlinkButton Grid.Column="0" NavigateUri="http://www.entityspaces.net" TargetName="New"><Image Source="EntitySpaces_Logo.jpg" Grid.Column="0" /></HyperlinkButton>
            <TextBlock Name="SearchTextBlock" Grid.Column ="1" Text="EntitySpaces 2009 Silverlight Demo" Foreground="Yellow" FontSize="14" Margin="10,5,10,5" VerticalAlignment="Center"></TextBlock>
            <ProgressBar Name="WorkingBar" Grid.Column="2" Foreground="Yellow" Background="Black" Value="0" Maximum="100" Margin="2,2,2,2" />
            <TextBox Name="SearchTextBox" Text="Enter Criteria Here" Grid.Column="3" Margin="20,0,20,0" Padding="10,5,10,5" FontSize="14" GotFocus="SearchTextBox_GotFocus"></TextBox>
            <Button Name="SearchButton" Content="Search" Grid.Column="4" FontSize="14" Click="SearchButton_Click"></Button>
        </Grid>
 
 
 
        <Grid Grid.Row="1" Margin="7">
            <data:DataGrid Name="EmployeesDataGrid" AutoGenerateColumns="False" >
 
                <data:DataGrid.Columns>
 
                    <data:DataGridTextColumn Binding="{Binding EmployeeID}" Header="Employee ID" IsReadOnly="True" />
                    <data:DataGridTextColumn Binding="{Binding FirstName}" Header="First Name" />
                    <data:DataGridTextColumn Binding="{Binding LastName}" Header="Last Name" />
                    <data:DataGridTextColumn Binding="{Binding HomePhone}" Header="Home Phone" />
                    <data:DataGridTextColumn Binding="{Binding City}" Header="City" />
 
                    <data:DataGridTemplateColumn Header="Hire Date" Width="160">
                        <data:DataGridTemplateColumn.CellTemplate>
                            <DataTemplate>
                                <TextBlock Text="{Binding HireDate, Mode=OneWay, Converter={StaticResource ShortDateConverter}}" VerticalAlignment="Center" Margin="2"/>
                            </DataTemplate>
                        </data:DataGridTemplateColumn.CellTemplate>
                        <data:DataGridTemplateColumn.CellEditingTemplate>
                            <DataTemplate>
                                <controls:DatePicker SelectedDate="{Binding HireDate, Mode=TwoWay}" />
                            </DataTemplate>
                        </data:DataGridTemplateColumn.CellEditingTemplate>
                    </data:DataGridTemplateColumn>
 
 
                    <data:DataGridTemplateColumn Header="Birth Date" Width="160">
                        <data:DataGridTemplateColumn.CellTemplate>
                            <DataTemplate>
                                <TextBlock Text="{Binding BirthDate, Mode=OneWay, Converter={StaticResource ShortDateConverter}}" VerticalAlignment="Center" Margin="2"/>
                            </DataTemplate>
                        </data:DataGridTemplateColumn.CellTemplate>
                        <data:DataGridTemplateColumn.CellEditingTemplate>
                            <DataTemplate>
                                <controls:DatePicker SelectedDate="{Binding BirthDate, Mode=TwoWay}" />
                            </DataTemplate>
                        </data:DataGridTemplateColumn.CellEditingTemplate>
                    </data:DataGridTemplateColumn>
 
                </data:DataGrid.Columns>
 
            </data:DataGrid>
        </Grid>
 
        <Grid Grid.Row="2" Margin="7">
 
            <Grid.ColumnDefinitions>
                <ColumnDefinition Width="*"></ColumnDefinition>
                <ColumnDefinition Width="75"></ColumnDefinition>
                <ColumnDefinition Width="15"></ColumnDefinition>
                <ColumnDefinition Width="75"></ColumnDefinition>
                <ColumnDefinition Width="15"></ColumnDefinition>
                <ColumnDefinition Width="75"></ColumnDefinition>
            </Grid.ColumnDefinitions>
 
            <Button Name="AddButton" Content="Add" Grid.Row="2" Grid.Column="1" FontSize="14" Click="AddButton_Click" ></Button>
            <Button Name="SaveButton" Content="Save" Grid.Row="2" Grid.Column="3" FontSize="14" Click="SaveButton_Click" ></Button>
            <Button Name="ClearButton" Content="Clear" Grid.Row="2" Grid.Column="5" FontSize="14" Click="ClearButton_Click" ></Button>
        </Grid>
 
    </Grid>
</UserControl>

 

Our Page.xaml.cs file is shown below. Take a look at the SearchButton_Click event. We build the EntitySpaces DynamicQuery and call the service.GetEmployeesAsync() method passing in the query in string form. In the service_GetEmployeesCompleted() method we access our EmployeesCollectionProxyStub class which was returned to us in the “e.Result” variable. However, now we are working with the client side lightweight proxy class. The interesting thing about this approach is that we are NOT using the Visual Studio generated proxies. Our proxies are smart and maintain row state, and they are going to get even smarter. This approach makes EntitySpaces a terrific architecture for building your Silverlight applications. The SaveButton_Click is also incredibly simple. The timer stuff you see is just to make the fancy progress bar work in the demo.

using System;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Media.Animation;
 
using EntitySpaces.SilverlightApplication.NorthwindClient;
using Proxies;
 
 
namespace EntitySpaces.SilverlightApplication
{
    public partial class Page : UserControl
    {
        private NorthwindClient.NorthwindClient service = new NorthwindClient.NorthwindClient();
        private Proxies.EmployeesCollectionProxyStub employees;
        private Storyboard Timer = new Storyboard();
        private int RecordsAdded;
 
 
        public Page()
        {
            InitializeComponent();
            Timer.Completed += new EventHandler(Timer_Completed);
            Timer.Duration = TimeSpan.FromMilliseconds(2);
        }
 
        private void SearchButton_Click(object sender, RoutedEventArgs e)
        {
            try
            {
                Proxies.EmployeesQueryProxyStub q = new Proxies.EmployeesQueryProxyStub("emp");
 
                q.Select(q.EmployeeID, q.FirstName, q.LastName, q.HomePhone, q.HireDate, q.BirthDate, q.City);
                q.Where(
                    q.FirstName.Like("%" + SearchTextBox.Text + "%") |
                    q.LastName.Like("%" + SearchTextBox.Text + "%"));
                q.OrderBy(q.LastName.Ascending);
 
                service.GetEmployeesCompleted += new EventHandler<GetEmployeesCompletedEventArgs>(service_GetEmployeesCompleted);
                service.GetEmployeesAsync(Proxies.EmployeesQueryProxyStub.SerializeHelper.ToXml(q));
 
                WorkingBar.Value = 0;
                Timer.Begin();
            }
            catch (Exception exc)
            {
                Console.WriteLine(exc.StackTrace);
            }
        }
 
        void service_GetEmployeesCompleted(object sender, GetEmployeesCompletedEventArgs e)
        {
            WorkingBar.Value = 100;
            Timer.Stop();
            
            if (e.Result != null)
            {
                employees = e.Result;
                EmployeesDataGrid.ItemsSource = employees.Collection;
            }
        }
 
        private void ClearButton_Click(object sender, RoutedEventArgs e)
        {
            SearchTextBox.Text = "";
            employees = null;
            EmployeesDataGrid.ItemsSource = null;
        }
 
        private void SaveButton_Click(object sender, RoutedEventArgs e)
        {
            try
            {
                if (employees == null) return;
 
                WorkingBar.Value = 0;
                Timer.Begin();
 
                service.SaveEmployeesCompleted += new EventHandler<SaveEmployeesCompletedEventArgs>(service_SaveEmployeesCompleted);
                service.SaveEmployeesAsync(employees);
            }
            catch (Exception exc)
            {
                Console.WriteLine(exc.StackTrace);
            }
        }
 
        private void AddButton_Click(object sender, RoutedEventArgs e)
        {
            if (employees == null)
            {
                employees = new EmployeesCollectionProxyStub();
                EmployeesDataGrid.ItemsSource = employees.Collection;
            }
 
            if (RecordsAdded++ < 5)
            {
                EmployeesProxyStub newEmp = new EmployeesProxyStub();
                newEmp.FirstName = "Scott";
                newEmp.LastName = "Schecter";
 
                employees.Collection.Add(newEmp);
            }
        }
 
        void service_SaveEmployeesCompleted(object sender, SaveEmployeesCompletedEventArgs e)
        {
            try
            {
                WorkingBar.Value = 100;
                Timer.Stop();
 
                RecordsAdded = 0;
 
                employees = e.Result;
                EmployeesDataGrid.ItemsSource = employees.Collection;
            }
            catch (Exception exc)
            {
                Console.WriteLine(exc.StackTrace);
            }
        }
 
        private void SearchTextBox_GotFocus(object sender, RoutedEventArgs e)
        {
            if (SearchTextBox.Text == "Enter Criteria Here")
            {
                SearchTextBox.Text = "";
            }
        }
 
        void Timer_Completed(object sender, EventArgs e)
        {
            WorkingBar.Value++;
            Timer.Begin();
 
            if (WorkingBar.Value > 100)
            {
                WorkingBar.Value = 1;
            }
        }
    }
}

Rather than repeat of bunch of content from previous posts, here are two posts that will help you further understand how we created the entire solution.

1) How we generated the lightweight client side proxies.

2) How we built the application and informed Visual Studio to use our proxies rather than generate proxies for us.

Be sure when you execute the “Generated Master” template to check the “Serializable Queries” checkbox on the advanced tab. Again, the demo is included in the latest alpha. We are even adding a new checkbox that will “scrunch” the XML when it goes over the wire so that your packets are much smaller. The XML will send all of your fields as “a1”, “a2”, “a3” and so on rather than “EmployeeID”, “FirstName”, “LastName”. This will make a big difference when sending large chunks of data from client to server and back again. Of course, we only send the columns that actually have data (non null/default) so your XML will be very tiny. This will not impact your proxies, they of course will still have your nice property names.

Well, that’s it for now. We are not only working on Silverlight and Proxies, we are also working through the Q3 Wish List as well.

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, a Silverlight application, a Mono application, 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.

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

posted on Thursday, July 16, 2009 10:42:46 PM (Eastern Standard Time, UTC-05:00)  #    Comments [0]
 Sunday, July 12, 2009

The Developer version and Source version have been published for this release. You must uninstall any prior versions of EntitySpaces 2009 including the production release or any prior alphas. EDIT – 2009-08-07: This Alpha only supports the EntitySpaces provider for SQL Server.

These are new features contained in this release:

  • The EntitySpaces Hierarchical Object Model Improvements
  • The EntitySpaces 2009 Getting Started PDF is now on the EntitySpaces 2009 menu after installation.
  • You can turn off the DateTime value in your class headers so that they wont cause differences in your source control system (in the settings tab).
  • Major Improvements to our lightweight client side proxies.
  • Our Silverlight demo which demonstrates using our proxies on both sides of the Silverlight / WCF conversation complete with editing and saving data through a grid. We will be posting the demo online so you can execute it and play with it. You will find it on our Samples menu after install it will compile right out of the box, just see the Readme.txt file in the solution.

Lightweight Client Side Proxy Stub – Major Improvements

The lightweight client side proxies now support

  • The INotifyPropertyChanged interface
  • ObservableCollections (great for Silverlight support)
  • And a Silverlight checkbox will we remove any non supported items such as [Serialized] attributes

image

We used the settings above settings to create the client side proxies for our Silverlight demo. Below is what our proxy collection looks like.

image

Noitce the Collection property is an ObservableCollection. In our Silverlight demo you can add records directly to your collection and they will automatically show up in the grid.

image

Above is our single Entity object. It implements the INotifyPropertyChanged interface. You can change a property directly on your Entity object it will immediately be reflected in the Silverlight grid.

We are adding a lot of enhancements to our lightweight client side proxies. You can begin your Silverlight application starting with this Alpha, it is working very well. A few things will be adding are a compressed mode where we will “Scrunch” the XML being sent over the wire by giving your property names in XML like “a1, a2, a3, a4, a5 …” and so on to reduce the size of the XML packet. This isn’t really an EntitySpaces issues its just the result of XML itself which is pretty bulky and will not effect your code in any way.

We will be hosting our new EntitySpaces Silverlight demo on our site and providing some insight on how it all operates. It is very simple to create Silverlight applications with EntitySpaces 2009 and the full demo is including with this latest alpha. The demo runs against Microsoft SQL’s Northwind database.

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, a Mono application, 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.

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

posted on Sunday, July 12, 2009 2:46:59 PM (Eastern Standard Time, UTC-05:00)  #    Comments [0]
 Wednesday, July 08, 2009
kick it on DotNetKicks.com

Okay, we finally got it!! We can honestly say getting a grip on Silverlight has been a real learning curve for our team, but it’s going to be a breeze for EntitySpaces customers because we’ve done all the research and laid all of the track. Our first approach was to use strings for everything because we didn’t want to use the “brain dead” proxies created by Visual Studio when you add a service reference to a Silverlight project. Then we figured out how we could force Visual Studio to use our client side proxies when adding a service reference. This is truly awesome. I cannot imagine a better way to write Silverlight applications than with EntitySpaces. What we are about to show you is so easy it will floor you. We will also be making a video on this and making our demo available with a future alpha or beta version. Okay, enough hype, show us already !!

image

Above, is our Silverlight Solution that contains everything needed to run the entire demo. Notice first, that we have all of the EntitySpaces runtime projects included rather than just references to the dlls (EntitySpace.Core35, etc.). We do this as we develop so we can debug and fix things if need be. Naturally, these project references are not required in your solution. You only need to add the runtime dll references to the project which houses your WCF service, EntitySpaces.SilverlightApplication.Web in this case.

Also notice the first project in the red box, EntitySpaces.Proxies.Silverlight. This is simply a Silverlight class library that we added to our solution. Then we generated our client side proxies into that solution. So now we have our client side proxies housed in a Silverlight class library. We could have just added these to our SilverlightApplication but there is a very important reason we didn’t. More on this later. These are generated via our Client Side Proxy Stub Template.

Next we have the SilverlightApplication project itself. This is the Silverlight application that runs in the browser. It references our EntitySpaces.Proxies.Silverlight class library that houses our client side proxies, and it references the EntitySpaces.DynamicQuery.Silverlight assembly because we want to be able to run full “es” DynamicQueries under Silverlight. Of course this project also contains our Page.xaml.cs file which contains our code that executes everything under Silverlight, we’ll be looking at that in a moment.

Finally, we have our EntitySpaces.SilverlightApplication.Web project which houses our WCF service in a web application. The two important files we’ll be looking at here are the INorthwind.cs file and the Northwind.svc.cs file.

Let’s start with the WCF Service

image

We have two methods. GetEmployees takes a serialized query in string form (the only time we have to use strings is with a query) and returns the data through our server side proxy class “EmployeesCollectionProxyStub”. Our Save method takes and returns a server side “EmployeesCollectionProxyStub” as well. The server side proxy stubs are generated via the Generated Master template. You indicate that you want them created via the Proxy/Stub tab as shown below. Also, be sure and check the “Serializable Queries” checkbox on the advanced tab.

image 

 

You can see how simple our WCF Service is in this example. Let’s look at the Northwind.svc.cs file.

image

First, look at the second method, our SaveEmployees() method. Could this be any easier? Not only do you not have to worry about which rows are added, modified, or deleted, but you can simply call Save, and return the very same collection. All new records, including their identity columns and such, will be returned to the Silverlight application so it can update it’s grid (in our case).

The GetEmployees method is a little more complicated, but not by much. It merely deserializes the string (a serialized proxy query) into a full blown EmployeesQuery, asks the EmployeesCollection to load it, then creates an EmployeesCollectionProxyStub class, passing in the EmployeesCollection, and returns it. Pretty simple really.

The Silverlight Application Logic

Let’s take a look at what our Silverlight Application looks like.

image

What the demo application does is create an EntitySpaces DynamicQuery when the user clicks on the Search button, calls our WCF service method GetEmployees(), then populates the grid with the data. The user can edit the data in the grid, and then merely click the Save button, which calls the WCF service method SaveEmployees(). Again, pretty simple.

So let’s look at our page.xaml.cs file. (We’ve removed any error handling to make the screen shot smaller.)

image

Notice in SearchButton_Click we create a EmployeesQueryProxyStub and use it exactly as we do with our full server side DynamicQuery objects, only we cannot load it directly. It must be serialized and sent to the server. In the last line of that method, we call our WCF service method GetEmployees().

In service_GetEmployeesCompleted() we assign e.Result to “employees”, which is our client side EmployeesCollectionProxyStub object, then we bind to employees.Collection, and our grid is populated.

Now, in the save button click event we intentionally set the first rows’ name to “GoogyGaga”, then add an additional Employee just for kicks, and call our WCF service method SaveEmployees(), which returns a refreshed collection, which we again assign to “employees”, and rebind the grid.

That’s it folks. An entire Silverlight application using EntitySpaces, showing both sides of the conversation. EntitiySpaces not only provides the glue between Silverlight and WCF, but it also provides all of the database access as well. All generated in mere seconds from your database schema via our Visual Studio Add in. Does it get any better than this?

Making Visual Studio Use the EntitySpaces Proxies instead of Visual Studio Generated Proxies

This is very cool indeed. We do not want to use Visual Studio generated proxy classes because they do not maintain row state for us (and other things). Our client side proxies maintain what rows are modified, added, and deleted such that you can send the entire collection back to the server and simply call Save() on it and bingo, it’s in the database. Here’s the trick. Remember the EntitySpaces.Proxies.Silverlight class library that houses our client side proxies? Well, there’s a reason we needed to have it housed in it’s own Silverlight class library and that is so we could tell Visual Studio to use it rather than generate proxies for us. Here’s how you do that when adding your Service Reference to the Silverlight application.

image

This is how we add our reference above. However, the trick to forcing Visual Studio to use our client side proxies is performed by pressing the “Advanced …” button.

image

Notice here that we tell it to reuse the types in our EntitySpaces.Proxies.Silverlight assembly. This is totally awesome. It’s great that Visual Studio allows us to do this. But even better, we were somewhat ahead of our time. Our client side proxies easily serialize into our server side proxies and vise versa. This is exactly what the DataContractSerializer is all about. It allows you to have different classes on each side of the conversation, and it works wonderfully in EntitySpaces.

Summary

This may seem like a lot to soak in but it really isn’t. We’ll be shipping our Silverlight demo hopefully with our next Alpha. Writing Silverlight applications is so graceful using EntitySpaces. Sure, you’re going to need to learn XAML and other things but all of the plumbing, wiring, and track have been laid for you. EntitySpaces has terrific Silverlight support. Everything you see here in this blog post works in our current alpha version. It’s late and we need to get some sleep, we are really jazzed about this and if anything we are understating how fantastic EntitySpaces is at providing the glue between Silverlight and WCF.

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, a Mono application, 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.

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

posted on Tuesday, July 07, 2009 11:43:13 PM (Eastern Standard Time, UTC-05:00)  #    Comments [0]
 Sunday, July 05, 2009

kick it on DotNetKicks.com

[UPDATED – SEE EntitySpaces, Silverlight, and WCF a Fantastic Combination FOR OUR NEW AND FAR SUPERIOR APPROACH]

Besides the enhancements mentioned in the DynamicQuery Enhancements post, this release addresses some important issues discovered in our previous alpha concerning Silverlight and WCF. You should uninstall the prior alpha before upgrading. Our Silverlight assembly is now named EntitySpaces.DynamicQuery.Silverlight.dll. There is, also, a new class called esDataContractSerializer (available in the .NET 3.5 assemblies) that can be used in any WCF or Silverlight application. Take a look at the code sample below which demonstrates an entire conversation from Server to Client and back to the Server again.  Using this approach all of your methods would use strings to send data to and receive data from the server. Of course, you can use the auto generated proxy classes created by Visual Studio but the nice thing about this approach is that the row-state of all of the data is maintained automatically and then saving becomes trivial.

public void TestCollection()
{
    EmployeesCollection coll = new EmployeesCollection();
    coll.Query.SelectAllExcept(coll.Query.Photo);
    coll.Query.es.Top = 3;

    if (coll.Query.Load())
    {
        // Create Our Server Side Proxy Stub
        BusinessObjects.EmployeesCollectionProxyStub server = new BusinessObjects.EmployeesCollectionProxyStub(coll);

        // Serialize it into a XML string and return this string to our Silverlight or WCF Client
        string xml = esDataContractSerializer.ToXml(server);

        // Deserialize the string above into our Client Side Proxy under Silverlight or our WCF Client
        Proxies.EmployeesCollectionProxyStub client = esDataContractSerializer.FromXml(xml, typeof(Proxies.EmployeesCollectionProxyStub))
            as Proxies.EmployeesCollectionProxyStub;

        // Set a property and notice that esRowState goes to Modified
        client.Collection[0].LastName = "Squarepants";

        // Serialize our Client Side Proxy into xml and send it back to the server
        xml = esDataContractSerializer.ToXml(client);

        // Deserialize it on the server back into a Server Side Proxy Stub, the esRowState is modifed as we would expect
        BusinessObjects.EmployeesCollectionProxyStub server1 = esDataContractSerializer.FromXml(xml, typeof(BusinessObjects.EmployeesCollectionProxyStub))
            as BusinessObjects.EmployeesCollectionProxyStub;

        // Now save the Entity
        server1.GetCollection().Save();
    }
}

You can also use this same approach with the single entity based proxies. For example, the EmployeeProxyStub class.

Some Silverlight / WCF Code

The PopulateEmployees() method below is the method that populates the grid in our soon to be released Silverlight demo. The method executes under Silverlight after the user types in his search criteria and hit’s the Search button. Notice that the query classes (both proxy and full server) contain their own ToXml / FromXml methods. This is because when we serialize and deserialize queries we are doing so for complex object graphs with circular references. This is more complex than what our esDataContractSerializer class is designed for.

private void PopulateEmployees()
{
    try
    {
        NorthwindClient.NorthwindClient service = new NorthwindClient.NorthwindClient();

        Proxies.EmployeesQueryProxyStub q = new Proxies.EmployeesQueryProxyStub("emp");
        q.Select(q.EmployeeID, q.FirstName, q.LastName, q.Title, q.HomePhone, q.HireDate, q.BirthDate);
        q.Where( q.FirstName.Like("%" + SearchTextBox.Text + "%") | q.LastName.Like("%" + SearchTextBox.Text + "%"));
        q.OrderBy(q.LastName.Ascending);
        q.es.Top = 5;

        // Notice we send the XML representation of the Query to the Server via the Async call “GetEmployees”
        service.GetEmployeesCompleted += GetEmployeesCompleted;
        service.GetEmployeesAsync(Proxies.EmployeesQueryProxyStub.SerializeHelper.ToXml(q));
    }
    catch (Exception exc)
    {
        Console.WriteLine(exc.StackTrace);
    }
}

The above code has called GetEmployees (a WCF service method on the server). This is what our WCF Service method on the server that receives the query looks like.

public string GetEmployees(string serializedQuery)
{
    List<Type> types = new List<Type>();
    types.Add(typeof(EmployeesQuery));

    // Deserialize our EmployeesQueryProxyStub class into our full blown server side query so we can execute it
    EmployeesQuery employeesQuery = EmployeesQuery.SerializeHelper.FromXml(
        serializedQuery, typeof(EmployeesQuery), types) as EmployeesQuery;

    EmployeesCollection employeesCollection = new EmployeesCollection();
    if (employeesCollection.Load(employeesQuery))
    {
        // Okay, we have loaded it, lets send the results back in string form
        EmployeesCollectionProxyStub proxy = new EmployeesCollectionProxyStub(employeesCollection);
        return esDataContractSerializer.ToXml(proxy);
    }

    return null;
}

Back under Silverlight in the browser our async GetEmployeesCompleted method is called, and we bind the data to the grid.

void GetEmployeesCompleted(object sender, GetEmployeesCompletedEventArgs e)
{
    try
    {
        WaitText.Visibility = Visibility.Collapsed;

        string serializedEmployees = e.Result;

        // Turn the XML into a Proxies.EmployeesCollectionProxyStub collection
        Proxies.EmployeesCollectionProxyStub employees = esDataContractSerializer.FromXml(
            serializedEmployees, typeof(Proxies.EmployeesCollectionProxyStub)) as Proxies.EmployeesCollectionProxyStub;

        // Now Databind
        EmployeesDataGrid.ItemsSource = employees.Collection;
    }
    catch (Exception exc)
    {
        Console.WriteLine(exc.StackTrace);
    }
}

This approach offers some real advantages. You can later send the serialized collection back to the server with added, updated, and deleted rows. Once on the server, deserialize it, and simply call Save on the full server side collection. This is because our proxies maintain the rowstate for you. We are still working out the kinks as we build our Silverlight application. The one problem we have right now is the Silverlight grid seems to revert back to the original data and lose our cell edits. However, this happens with the Visual Studio proxies as well. Once we get this issue resolved and are fully saving data, we will publish our Silverlight demo. If you want to use this technique, you will need to generate the client side proxies and include them in your Silverlight or WCF client application. Be sure and click the new checkbox named “Serializable Queries” on the Advanced Tab of the Generated Master template. However, as you can see from the DynamicQuery Enhancements post, we are doing more than just addressing Silverlight and WCF development.

The bug that was affecting project files has been fixed. This occurred if you edited a template instance in an existing project, and saved without visiting all of the tabs. With this fix, un-visited tabs no longer revert to their default values. There is also a Twitter toolbar button on the What’s New page so you can easily get to our Twitter page. This alpha still only supports Microsoft SQL Server.

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, a Mono application, 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.

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

posted on Sunday, July 05, 2009 10:49:49 PM (Eastern Standard Time, UTC-05:00)  #    Comments [0]
 Sunday, June 28, 2009

We are pleased to make this new release available to current customers, there is no trial version available at this point. This release provides our DynamicQuery API built into the Client Side Proxy Stubs. The new serializable DynamicQuery’s should be Silverlight compliant as well. This release is for those who are using WebServices, Silverlight, or WCF and would like to explore our new DynamicQuery serialization feature. We will be making the source code available for our source code customers for this Alpha release as well. The release notes along with some breaking changes are at the end of this blog post (READ BEFORE INSTALLING). An upcoming Beta release will consist of much of what was requested in the Q2 Wish List forum. Just a reminder the current production release is version 2009.1.0209.0.

For more information on our new Serializable DynamicQuery’s see these two posts:

Because the two blog posts above are only in C# here is a VB.NET sample (without the proper cleanup code on the streams and such)

Private Sub QuerySerializerForm_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load

    Dim o As New Proxies.OrdersQueryProxyStub("o")
    Dim q As New Proxies.EmployeesQueryProxyStub("emp")
    q.SelectAll()
    q.Select(q.LastName.ToLower().Substring(2, 4), o.Freight, (q.FirstName + "," + q.Address).As("Mike"))
    q.LeftJoin(o).On(q.EmployeeID = o.EmployeeID)
    q.Where(q.EmployeeID > 30)
    q.OrderBy(q.LastName.Descending)
    q.es.Top = 50

    Dim xml As String = q.Serializer.ToXml()

    Dim memoryStream As New MemoryStream(Encoding.Unicode.GetBytes(xml))

    Dim reader As XmlDictionaryReader
    reader = XmlDictionaryReader.CreateTextReader(memoryStream, Encoding.Unicode, New XmlDictionaryReaderQuotas(), Nothing)

    Dim types As New List(Of System.Type)
    types.Add(GetType(EmployeesQuery))
    types.Add(GetType(OrdersQuery))

    Dim emp As New EmployeesQuery()
    Dim dcs As DataContractSerializer
    dcs = emp.Serializer.GetSerializer(types)

    emp = CType(dcs.ReadObject(reader), EmployeesQuery)

    Dim coll1 As New EmployeesCollection()
    coll1.Load(emp)

End Sub

Now, in reality you shouldn’t have to do any of the manual serialization we are doing here, but of course you can if you want to. You will want to use the [KnownTypes] attribute if you are using WCF on the Server Side.

 

             RELEASE NOTES

                EntitySpaces 2009.1.0629.0 Alpha Release
                            June 29th, 2009
==================================================================================

  • This release will not run side by side with your current ES2009 installation, it will overwrite the installation even if you choose another folder. You should uninstall any prior release before installing the Alpha version.
  • The new Serializable DynamicQuery functionality requires .NET 3.5 SP1.
  • The Silverlight version of the EntitySpaces.DynamicQuery.dll is in the “C:\Program Files\EntitySpaces 2009\Runtimes\.NET 3.5\Silverlight” folder
  • There is a new checkbox on the "Advanced" tab of the "Generated Master" template named "Serializable Queries (requires .NET 3.5 SP1)" that you must check in order to use the new serializable queries.
  • When you generate your client side proxies via the "Client Side Proxy/Stub" template you will now have a client side DynamicQuery class.
  • The only data provider in this Alpha - EntitySpaces.SqlClientProvider.dll

NOTE: The breaking changes listed below should generate compile time errors, not runtime errors. Adding a reference to Entityspaces.DynamicQuery.dll to your project, and adding a "using EntitySpaces.DynamicQuery;" line to each file that has a "using EntitySpaces.Interfaces;" line should clear most of the compile errors. ("Imports EntitySpaces.DynamicQuery" for VB users.)

  • Breaking change - There is a new assembly named EntitySpaces.DynamicQuery.dll which is now a required assembly reference for all applications. This assembly should be Silverlight compliant and is the only EntitySpaces assembly needed to use the DynamicQuery's under Silverlight. The inheritance is different for the full blown server side DynamicQuery's versus the client side queries.

       Server Side DynamicQuery

          EmployeesQuery -> esEmployeesQuery -> esDynamicQuery –> esDynamicQuerySerializable

       Client Side Proxy DynamicQuery

          EmployeesQueryProxyStub -> esDynamicQuerySerializable

NOTE: The esDynamicQuery class lives in EntitySpaces.Interfaces.dll just as always, however, most of the logic behind the DynamicQuery now lives in the new esDynamicQuerySerializable class which lives in EntitySpaces.DynamicQuery.dll.

  • Breaking change - There is a minor change in the DynamicQuery API with the ".es" property. This is only for the DynamicQuery class, the Entity and Collection classes have no change in this area.

   Before the Alpha you could do this:

     EmployeesQuery query = new EmployeesQuery();
     query.es.Connection.Name = "SomeName";


   Now the connection is accessible this way ...

     EmployeesQuery query = new EmployeesQuery();
     query.es2.Connection.Name = "SomeName";

     ** Notice we use "es2" however all of the other properties are still available under the ".es" property.

   There is also a new helper when using the DynamicQuery features:

     EmployeesQuery query = new EmployeesQuery();
     query.es.Serializer.[helper methods]


   which can be used if necessary to serialize.

  • Breaking change - Many Enums that used to be in EntitySpaces.Interfaces are now in EntitySpaces.DynamicQuery

    These included:

    esQueryType
    esQuerySubOperatorType
    esOrderByDirection
    esConjunction
    esSystemType

    As well as some other internal enums.

  • Breaking change - esWhereItem was renamed to esComparison and now lives in EntitySpaces.DynamicQuery.dll. Unless you are manually creating this class which is rare you will not be affected.
  • Breaking change - esSelectItem was renamed to esExpression and now lives in EntitySpaces.DynamicQuery.dll. Unless you are manually creating this class which is rare you will not be affected.

 

We hope to have an entirely new Silverlight / WCF Demo available to coincide with and built from the upcoming Alpha release. Of course we will do a blog post on that as well. When you see it in action you will be amazed how easy it is. We still have a few issues to work out but things are moving very rapidly now. Imagine having what appears to be the full EntitySpaces API available to you on a client somewhere and only needing to have a single 52k assembly present, and it is fully Silverlight compliant as well. This is just one thing our upcoming release will provide.

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, a Mono application, 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.

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

posted on Sunday, June 28, 2009 8:32:51 PM (Eastern Standard Time, UTC-05:00)  #    Comments [0]
 Tuesday, June 16, 2009

This stuff is hot guys and gals. We are asking Jon Davis to write an entirely new Silverlight demo that will showcase our DynamicQuery feature running under Silverlight inside the browser and hitting a WCF service on the server. We cannot wait, this is so slick … Here’s another sneak peak post.

First the Client Code

Notice here we are using new “QueryProxyStub” classes that are available in through our proxy template (in addition to the existing single object and collection).

Proxies.OrdersQueryProxyStub o = new Proxies.OrdersQueryProxyStub("o");
Proxies.EmployeesQueryProxyStub q = new Proxies.EmployeesQueryProxyStub("emp");
q.Select(q.LastName.ToLower().Substring(2, 4), o.Freight, (q.FirstName + "," + q.Address).As("Mike"));
q.LeftJoin(o).On(q.EmployeeID == o.EmployeeID);
q.Where(q.EmployeeID > 30);
q.es.Top = 50;

// Manually convert it (you won’t need to do this)
string xml = q.Serializer.ToXml();

Their is a new property on the Query called Serializer than can help with certain serialization issues, for the most part however you shouldn’t have to use it. But it’s nice to have around, above we serialize our query to XML via the WCF DataContractSerializer (the entire object graph) via the ToXml() method.

 

Now the Server Code Deserializing (Simulated)

Notice below that we deserialize the XML from our QueryProxyStub classes into our full blown server side Query classes so that we can execute them. In reality the code that you will write on the server will be much simpler than the code shown below. You will use the KnownTypeAttribute on your WCF Service methods. We will have a full sample showing how this works, don’t let the code below scare you, it’s so easy. This is just test harness code but it works just fine.

using (MemoryStream memoryStream = new MemoryStream(Encoding.Unicode.GetBytes(xml)))
{
    using (XmlDictionaryReader reader =
        XmlDictionaryReader.CreateTextReader(memoryStream, Encoding.Unicode,
        new XmlDictionaryReaderQuotas(), null))
    {
        types = new List<Type>();
        types.Add(typeof(EmployeesQuery));
        types.Add(typeof(OrdersQuery));

        EmployeesQuery emp = new EmployeesQuery();
        DataContractSerializer dcs = emp.Serializer.GetSerializer(types);

        // Deserialize
        emp = dcs.ReadObject(reader) as EmployeesQuery;

        EmployeesCollection coll1 = new EmployeesCollection();
        if (coll1.Load(emp))
        {
            // It worked
        }
    }
}

At this point we could return the newly loaded collection back to the client and it would implicitly be returned as a ProxyCollection.

The Demo

We hope to have an entirely new Silverlight / WCF Demo available to coincide with and built from the upcoming Alpha release. Of course will we do a blog post on that as well. When you see it in action you will be amazed how easy it is. We still have a few issues to work out but things are moving very rapidly now. Imagine having what appears to be the full EntitySpaces API available to you on a client somewhere and only needing to have a single 52k assembly present, and it is fully Silverlight compliant as well. This is just one thing our upcoming release will provide.

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, a Mono application, 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.

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

posted on Tuesday, June 16, 2009 10:40:36 PM (Eastern Standard Time, UTC-05:00)  #    Comments [0]
 Saturday, June 13, 2009
kick it on DotNetKicks.com

We have decided to use the WCF DataContract approach when serializing our enhanced DynamicQuery’s. In our upcoming alpha release, our DynamicQuery classes now live in a separate assembly that can execute on the client side along with your EntitySpaces proxies without requiring either the EntitySpaces.Core or the EntitySpaces.Interfaces assemblies. The EntitySpaces.DynamicQuery assembly (only 52k in size) is also compatible with Silverlight and can run down inside of the browser. The older .NET 2.0 serialization techniques aren’t supported under Silverlight and having this feature work under Silverlight is important to us. At this moment, the Alpha will require .NET 3.5 SP1 (if you want to use these advanced new features) as it provides the ability to serialize object graphs having circular references. Currently, our DynamicQuery API does have circular references. For instance, SelectColumns have a reference to their parent DynamicQuery object. There is a very good summary of this feature in .NET 3.5 SP1 HERE and you might want to take a look at it. More on this later however.

Take a look at this very simple query. The example code below shows a query that will ultimately do a join and is selecting columns from both the Employees and Products tables. We also call ToLower, Substring, and Sum.

ProductsQuery prod = new ProductsQuery();

EmployeesQuery emp = new EmployeesQuery();
emp.Select(emp.LastName.ToLower().Substring(2, 4), prod.QuantityPerUnit.Sum().As("Qty"), emp.FirstName);

Here is an example of what one of the internal classes in our DynamicQuery API looks like. It’s ugly because we have to use #if #else #endif syntax, but just be glad you guys never have to write such code. We need to make sure the old and the new serialization both work. Notice the DataContract and DataMember attributes. Again, these are on our internal DynamicQuery API classes. Also, don’t let the WCF term scare you, these features can be used in non WCF scenarios as well.

WCFClass

Below is some test code that we use to manually invoke the DataContractSerializer.

List<System.Type> types = new List<System.Type>();
types.Add(typeof(ProductsQuery));

DataContractSerializer dcs = new DataContractSerializer(typeof(EmployeesQuery), "Query", "es", types);
var ms = new MemoryStream();
dcs.WriteObject(ms, q);
ms.Seek(0, SeekOrigin.Begin);

StreamReader sr = new StreamReader(ms);
string xml = sr.ReadToEnd();

Now, if you want to see what the resulting XML looks like click on this LINK. Admittedly, the XML is pretty funky because it creates what are essentially pointers to objects that appear in the XML graph multiple times. However, this saves a ton of space and of course prevents an endless loop when trying to serialize circular references.

Our development test harness for this is shown below:

WCFTestHarness

Of course, when serializing and sending queries in XML over the wire, you are probably going to want to be using HTTPS so that sensitive data cannot be seen or tampered with.

What does this all mean?

Well, this means that our DynamicQuery’s can optionally be built into your proxy objects and used from the client side just as you would on the server side, only you will send your query over to the server and it will return either a proxy entity or proxy collection. Using our proxies with built in queries will feel like full blown EntitySpaces on the client side. And this will all run under Silverlight as well. Couple that with the massive improvements coming in our DynamicQuery API and that is some very cool functionality. Even if you aren’t interested in all this client side serialization stuff, you will love the enhancements coming in the DynamicQuery API. And remember, this will all work for web services too.

Before we release to production, we might be able to eliminate the circular references in our DynamicQuery object graph, however, this is not an easy thing to do. We do have a working solution via the enhancements in the .NET 3.5 SP1 release with the circular references in place.

Breaking Changes?

We are renaming quite a few internal classes. Some of them are public. For instance, esWhereItem is now called esComparison and esSelectItem is now called esExpression. Our queries are basically made up of esExpressions which are then combined with operators such as != or == to form esComparisons. The reason we needed to change these names is that they were too specific. We are going to allow you to use complex syntaxes in OrderBy, GroupBy and many other areas within the query syntax itself. Therefore, esWhereItem and esSelectItem just weren’t appropriate names. Most of you never really manually create these objects so it wont impact you at all. However, if you do, you will have to do a find/replace on these if you are manually creating them in code (which is rare).

Where are we at?

We are pushing very hard for our Alpha release to be released by the end of this month. Right now the carburetor is lying on the floor and we’re all absolutely covered in grease. However, we know how to put this back together again and when we do it’s going to be awesome. We are really excited about this release and the Q2 Wish List Forum will play, and is playing, heavily into what we deliver.

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, a Mono application, 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.

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

posted on Saturday, June 13, 2009 10:44:40 PM (Eastern Standard Time, UTC-05:00)  #    Comments [0]
 Sunday, March 01, 2009
kick it on DotNetKicks.com     Shout it

Can you Query me now?mobile (Silverlight, WCF, Webservices, and Mobile)

EntitySpaces 2009 Q2 is going to revolutionize your ability to use the EntitySpaces 2009 architecture on the client side of any two-way conversation, whether it be a Silverlight, WCF, or a webservices conversation. In fact, you will be able to work on the client side as if the full EntitySpaces architecture was at your disposal but without actually requiring the EntitySpaces architecture be present on the client. "But how can that be?" you wonder. Continue reading and we will explain.

EntitySpaces has always had good support for mobile applications via our Compact Framework support. We even generate "smarter" proxies than the ones generated by Visual Studio for WCF or webservices scenarios. Our proxies maintain row state such as (inserted, updated, and deleted) such that all that is required is that you send the data back to the server and commit it.  But this client side proxy support is about to become much, much more powerful and can be used for non-mobile scenarios such as Silverlight, WCF, and webservices. With our enhanced proxies (especially for mobile applications where space is limited) this can prove to be a very powerful way to use EntitySpaces. We like to think of this as a sort of "Virtual EntitySpaces Mode" as it feels just like EntitySpaces only it really doesn't require the full architecture on the client side. So, let's dive into this and see how it works starting with a review of our current proxy support.
 

Our Current Client Side Proxy Functionality

The EntitySpaces Client Side proxies offer the ability to easily work with EntitySpaces on the client side of a two way conversation without requiring any of the EntitySpaces assemblies. Our proxies also track the dirty state for you so that when you send data back to the server EntitySpaces automatically knows whether to insert, update, or delete the data. This functionality is already built into the currently shipping ES2009 Q1 release. The template that you use to create the Client Side proxies is highlighted below.

ProxyStubTemplate

When you execute the "Client Side Proxy/Stub" template there are currently two classes generated for you, the Collection and Entity class. Shown below are the proxy stub classes that were generated by the "Client Side Proxy/Stub" template for the Microsoft Northwind Suppliers table. Notice that the classes do not inherit from any base classes nor do they require any of the EntitySpaces assemblies. Also, in the SuppliersProxyStub (entity) class notice the esRowState property. This is the property that EntitySpaces uses to determine the state of the entity (inserted, updated, or deleted) and the proxy is smart enough to set this property for you based on the actions you take (you do not have to worry about setting it). These two classes are extremely small and lightweight in size.

proxystub1

With these two classes you work with data on the client side of a conversation without EntitySpaces being present, but something is missing, a feature that hooks most EntitySpaces developer once they start using it.

New Functionality Coming in ES2009 Q2

In our ES2009 Q2 release the Client Side template will now generate a new, optional, third class, the "QueryProxyStub" class. Yes, you guessed it, the full EntitySpaces DynamicQuery API now available on the client side of a two-way conversation. Take a look at the SuppliesQueryProxyStub class below. This class is just like the DynamicQuery classes you are accustomed to using already only it inherits from a new class named esDynamicQuerySerializable. If you take a close look at the methods in the esDynamicQuerySerializable class you will notice that there are no methods to load or execute the query itself (more on this later). This query can only be created, defined, and then serialized back to the server (a very cool way to write a Silverlight application). If you have never seen how powerful our DynamicQuery API is check out our Showcase post HERE.

proxystub2

Now, imagine that you're on the client side of a WCF conversation or even running down inside the browser in a Silverlight application and you need to query your Supplier table for data. No problem, here is how you would accomplish that task with the new proxy query class.

SuppliersQueryProxyStub sQuery = new SuppliersQueryProxyStub ();
sQuery.Select(sQuery.SupplierID, sQuery.Region);
sQuery.Where(sQuery.Country == "Spain");

Notice that we do not call sQuery.Load(). This is because the esDynamicQuerySerializable has no way to actually load data, it represents the query only, the ability to load it (or execute it) exists on the server side of the conversation. Also, the full join syntax is available although it is not shown above in the query. The proxy queries are fully serializable which is the key to how it works. At a very high level this is how you would fetch data from the server, imagine a method like this:

public SuppliersCollectionProxyStub FetchSupplers(SuppliersQueryProxyStub query)

You would transmit the proxy stub query to the server, where it will be deserialized, assigned to a full server query object, executed, and then the resulting proxy stub collection would be returned. The code will look very much like this.

public SuppliersCollectionProxyStub FetchSupplers(SuppliersQueryProxyStub query)
{
    SuppliersCollection coll = new SuppliersCollection();
    coll.Query = query as esDynamicQuerySerializable;
    coll.Query.Load();

    // more code below ...
}

Notice how we are able to merely assign our SuppliersQueryProxyStub object to the full blown SuppliersCollection's query object and then execute it. Could it be any easier?

EntitiySpaces.DynamicQuery - A New Assembly

Just where does this esDynamicQuerySerializable class that our SuppliersQueryProxyStub inhertis from live? The answer is a new assembly that will ship with ES2009 Q2 named EntitySpaces.DynamicQuery.dll. This is very tiny (less that 50k) assembly that only references System.Core and System.XML and is fully Silverlight 2.0 compliant. It does not link with EntitySpaces.Core or EntitySpaces.Interfaces. However, even better we are not maintaining two separate DynamicQuery API's. This new assembly and class is used on the server side as well, which means this new assembly is required now for EntitySpaces applications. Look at the diagram below which shows the hierarchy of a normal DynamicQuery class as generated by the ES2009 Q2 Generated Master template. This preserves your current API.

proxystub3

Notice the the original base class esDynamicQuery is still there, however, it now inherits from the esDynamicQuerySerializable class. In order to run under Silverlight our client side DynamicQuery assembly could not reference the System.Data namespace, so we have separated the original esDynamicQuery into the two classes you see above.

What Does it All Mean?

Our new enhanced client side proxies will allow you to have a "Virtual EntitySpaces Architecture" running almost anywhere including mobile devices, Silverlight applications, WCF scenarios, and webservices. It will act and feel just like EntitySpaces Of course, we can already run in all of these environments but with ES2009 Q2 and the addition of the DynamicQuery proxy and the massive DynamicQuery API enhancements that are also coming you will truly be blown away by the productivity and reach of the EntitySpaces Architecture. The only thing that is required on the client to make this all possible is the tiny EntitySpaces.DynamicQuery assembly (less than 50k) which is completely Silverlight compliant. There are other enhancements that will be made to the proxies but we will keep them small and lightweight.

There are also a few technical issues we must solve yet, though most have been worked out. For example, where do the extra properties go when you bring them back via a join? In the full server side classes this is handled gracefully, and we make those properties appear as if there are in your strongly typed entities via sophisticated binding support. How do we do this on the client side? These are a few of the issues we must solve yet.

We find this new support terribly exciting and it presents almost boundless usage scenarios. Especially when you factor in the enhancements we are making to DynamicQuery API itself, but that is the topic for another post. And keep those comments coming in our ES2009 Wish List forum, we are listening and will implement a lot of your requested features.

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, a Mono application, 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.

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

posted on Sunday, March 01, 2009 1:31:36 PM (Eastern Standard Time, UTC-05:00)  #    Comments [0]
 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]
 Thursday, January 15, 2009

The Developer Site

We are working hard on expanding our new developer site and you should definitely begin to use this site. The search feature is very good. More and more on our forums we will be pointing you to the developer site. All of the samples are provided in C# and VB.NET. Two recent additions include:

  • EntitySpaces 2009 Application Documentation

http://www.developer.entityspaces.net/documentation/EntitySpaces2009/WhatsNew.aspx

  • SubQuery Documentation

http://www.developer.entityspaces.net/documentation/DynamicQuery/SubQuery/SelectSubQuery.aspx

VB.NET Sample Application

We will also be providing a VB.NET sample application matching our current C# sample with both the Trial and Developer installs.

WCF Sample Application

Finally, we are creating a very informative WCF sample application that will be available for download. It will also be presented most likely in a two part blog posting as well (and included in our developer site). This sample app will demonstrate end-to-end how to use our Full Proxy (FP) and Lightweight Proxies (LP) in WCF scenarios.

wcf_sample

 

So, remember to search on our developer site before posting on our forums to see if you can find your answer there. Remember, we will continually be adding new content.

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, a Mono application, 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.

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

posted on Thursday, January 15, 2009 11:20:53 PM (Eastern Standard Time, UTC-05:00)  #    Comments [0]
 Friday, May 23, 2008

EntitySpaces and Silverlight Demo

Part 2: Filtering and Changing EntitySpaces Data

kick it on DotNetKicks.com

Jon_Davis
Written by Jon Davis
http://www.jondavis.net/

 

 

Run the Demo Here  ==> http://developer.entityspaces.net/ES2008/Demos/Silverlight/PartTwo
Download the Source Here ==> http://www.developer.entityspaces.net/downloads/EntitySpacesSilverlightDemo2.zip 
 

Review of Part One

In Part One, I described the process of getting Silverlight to interact with a WCF web service, and I showed how I bound EntitySpaces based data objects (WCF client proxies) to Silverlight controls, specifically a DataGrid control. While there were a lot of pages of review in Part One, it was mostly point-and-click “configuration coding”, as MyGeneration, EntitySpaces, and Visual Studio did most of the work for me.

linqII_one

Figure 1 - EntitySpaces RIA running in Safari 3.1 (on Windows) with just about 20 lines of hand-written client-server code and XAML markup.

 

But showing data in a grid isn’t very exciting. It’s time to look at some interaction with data and give EntitySpaces a little more credit than just a data wrapper.

 

Category-Filtered Products (Client-Server Method)

Let’s assume that the user wants to filter the products list by category. I want to keep this demonstration as simple as possible, while proving out technical implementations of basic scenarios, so I’m not going to make any significant effort just yet to make this look pretty.

linqII_two  

Here’s the XAML:

<UserControl
    x:Class="EntitySpacesSilverlightDemo_Silverlight.Page"
    xmlns:Controls="clr-namespace:System.Windows.Controls;assembly=System.Windows.Controls.Data" 
    xmlns="http://schemas.microsoft.com/client/2007"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
    <Grid x:Name="LayoutRoot" Background="Gray">
        <Grid.RowDefinitions>
            <RowDefinition Height="75" />
            <RowDefinition />
        </Grid.RowDefinitions>
        <TextBlock Grid.Row="0" Text="EntitySpaces on Silverlight ~ Northwind Demo" VerticalAlignment="Center" HorizontalAlignment="Center" />
        <Grid Grid.Row="1">
            <Grid.ColumnDefinitions>
                <ColumnDefinition Width="200" />
                <ColumnDefinition />
            </Grid.ColumnDefinitions>

            <TextBlock VerticalAlignment="Center" HorizontalAlignment="Center" Text="Please Wait" Visibility="Collapsed" x:Name="WaitText" />
            <ListBox Width="300" Grid.Column="0" x:Name="ViewSelector" SelectionChanged="ViewSelector_SelectionChanged">
                <ListBoxItem Content="Products: All"></ListBoxItem>
            </ListBox>

            <Controls:DataGrid AutoGenerateColumns="True" x:Name="ESDataGrid" Grid.Column="1" />
        </Grid>
    </Grid>
</UserControl>

For starters and for the sake of continuing the discussion of ES over WCF, I’m going to make this a client-server filter—I’ll pass in a CategoryID as a parameter in my WCF request for products.

Here’s the complete client-side code-behind for Page.xaml.cs, additions in bold+brown:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using System.Net;

using EntitySpacesSilverlightDemo_Silverlight.Northwind;

namespace EntitySpacesSilverlightDemo_Silverlight
{
    public partial class Page : UserControl
    {
        NorthwindClient.NorthwindClient ESNorthwind;

        public Page()
        {
            InitializeComponent();
            ESNorthwind = new NorthwindClient.NorthwindClient();

            ESNorthwind.GetCategoriesCompleted += ApplyCategoriesToList;
            ESNorthwind.GetProductsCompleted += new EventHandler<NorthwindClient.GetProductsCompletedEventArgs>(NorthwindClient_GetProductsCompleted);
            ESNorthwind.GetProductsByCategoryCompleted += new EventHandler<GetProductsByCategoryCompletedEventArgs>(Northwind_GetProductsByCategoryCompleted);

            GetCategories();

            LoadAllProducts();
        }

        private void GetCategories()
        {
            ESNorthwind.GetCategoriesAsync();
        }

        private void ApplyCategoriesToList(object sender, GetCategoriesCompletedEventArgs e)
        {
            if (e.Error == null)
            {
                Categories[] cc = e.Result.Collection;
                for (int i = cc.Length-1; i >=0; i--)
                {
                    Categories category = cc[i];
                    ListBoxItem lbi = new ListBoxItem();
                    lbi.Tag = "CategoryID: " + category.CategoryID;
                    lbi.Content = "Products: " + category.CategoryName;
                    ViewSelector.Items.Insert(1, lbi);
                }
            }
        }

        private void LoadAllProducts()
        {
            WaitText.Visibility = Visibility.Visible;
            ESNorthwind.GetProductsAsync();
        }

        void LoadProductsByCategory(int categoryId)
        {
            WaitText.Visibility = Visibility.Visible;
            ESNorthwind.GetProductsByCategoryAsync(categoryId);
        }

        void Northwind_GetProductsByCategoryCompleted(object sender, GetProductsByCategoryCompletedEventArgs e)
        {
            WaitText.Visibility = Visibility.Collapsed;
            ProductsCollection pc = e.Result;
            ESDataGrid.ItemsSource = pc.Collection;
        }

        void NorthwindClient_GetProductsCompleted(object sender, Northwind.GetProductsCompletedEventArgs e)
        {
            WaitText.Visibility = Visibility.Collapsed;
            ProductsCollection pc = e.Result;
            ESDataGrid.ItemsSource = pc.Collection;
            ESDataGrid.Columns[ESDataGrid.Columns.Count - 1].Visibility = Visibility.Collapsed; // hide "esRowState"
        }

        private void ViewSelector_SelectionChanged(object sender, SelectionChangedEventArgs e)
        {
            ListBoxItem lbi = ViewSelector.SelectedItem as ListBoxItem;
            if (lbi != null)
            {
                if (lbi.Content.ToString() == "Products: All")
                {
                    LoadAllProducts();
                    return;
                }
                string tag = lbi.Tag as string;
                if (tag != null && tag.StartsWith("CategoryID: "))
                {
                    tag = tag.Substring(12);  // length of "CategoryID:"
                    LoadProductsByCategory(int.Parse(tag));
                }
            }
        }

    }
}

On the server, we will perform a basic EntitySpaces query operation.

INorthwind service interface:
[ServiceContract]
public interface INorthwind
{
    [OperationContract]
    ProductsCollectionProxyStub GetProducts();

    [OperationContract]
    ProductsCollectionProxyStub GetProductsByCategory(int categoryId);
    [OperationContract]
    CategoriesCollectionProxyStub GetCategories();
}

Northwind service implementation:
public class Northwind : INorthwind
{
    public ProductsCollectionProxyStub GetProducts()
    {
        ProductsCollection pc = new ProductsCollection();
        pc.LoadAll();
        ProductsCollectionProxyStub pcs = new ProductsCollectionProxyStub(pc);
        return pcs;
    }

    public ProductsCollectionProxyStub GetProductsByCategory(int categoryId)
    {
        ProductsCollection pc = new ProductsCollection();
        pc.Query.Where(pc.Query.CategoryID.Equal(categoryId));
        pc.Load(pc.Query);

        ProductsCollectionProxyStub pcs = new ProductsCollectionProxyStub(pc);
        return pcs;
    }

    public CategoriesCollectionProxyStub GetCategories()
    {
        CategoriesCollection cc = new CategoriesCollection();
        cc.LoadAll();

        // strip out the OLE bitmaps
        for (int i = 0; i < cc.Count; i++)
        {
            cc[i].Picture = null;
        }

        CategoriesCollectionProxyStub ccs = new CategoriesCollectionProxyStub(cc);
        return ccs;
    }

}

Category-Filtered Products (Local Filtering Method)

Practically speaking, calling out to the server every time you want to filter the products is bad design unless the Products list contains a lot (hundreds of thousands) of records, in which case we should also drop the “Products: All” unfiltered option from the ListBox so that the user cannot make the mistake of loading all products which might take forever.

If the unfiltered source data is relatively small, as Northwind’s Products table actually is, then it would make more sense to load all products from the server and then filter against the category locally. This eliminates the HTTP-based callback to the server and makes the user’s experience much faster and more responsive.

LINQ-to-Objects is supported in Silverlight, and this includes LINQ-to-EntitySpaces-client-proxies. We can change the NorthwindClient_GetProductsCompleted and ViewSelector_SelectionChanged methods to use LINQ filtering rather than server-side filtering. In so doing, we can remove much of the code we just added and achieve the same results but executing much faster.

Products[] NorthwindProducts = null;
void NorthwindClient_GetProductsCompleted(object sender, Northwind.GetProductsCompletedEventArgs e)
{
    WaitText.Visibility = Visibility.Collapsed;
    NorthwindProducts = e.Result.Collection;
    ESDataGrid.ItemsSource = NorthwindProducts;
    ESDataGrid.Columns[ESDataGrid.Columns.Count - 1].Visibility = Visibility.Collapsed; // hide "esRowState"
}

private void ViewSelector_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
    ListBoxItem lbi = ViewSelector.SelectedItem as ListBoxItem;
    if (lbi != null)
    {
        if (lbi.Content.ToString() == "Products: All")
        {
            ESDataGrid.ItemsSource = NorthwindProducts;
            ESDataGrid.Columns[ESDataGrid.Columns.Count - 1].Visibility = Visibility.Collapsed; // hide "esRowState"
            return;
        }
        string tag = lbi.Tag as string;
        if (tag != null && tag.StartsWith("CategoryID: "))
        {
            int catID = int.Parse(tag.Substring(12));
            ESDataGrid.ItemsSource =
                from p in NorthwindProducts
                where p.CategoryID == catID
                select p;
            ESDataGrid.Columns[ESDataGrid.Columns.Count - 1].Visibility = Visibility.Collapsed; // hide "esRowState"
        }
    }
}

We can now eliminate one of the INorthwind interfaces we just added, ..

  • GetProductsByCategory(int categoryId)

.. and we can eliminate some of the just-added client/server handling code in Silverlight:

  • LoadProductsByCategory(int categoryId)
  • Northwind_GetProductsByCategoryCompleted(...)

Changing Data

Let’s assume that the user is an administrator who is maintaining this list of products and needs to be able to make changes to product data on the fly. The bad news is that in the interest of focusing on EntitySpaces and less on Silverlight UI, I intended to refrain from creating a pop-up editor for editing a record. The good news is that the Silverlight DataGrid supports two-way databinding and inline edits, and in such case one would need no layout changes at all. I only need to add an event handler for DataGrid edits and pass the revised record up to the server via WCF.

We’ll bind to the CommittingCellEdit and CommittingRowEdit events. In CommittingCellEdit we’ll update the property that was edited, and in CommittingRowEdit we’ll pass the Product out to the server.

Page.xaml (modify):

<Controls:DataGrid AutoGenerateColumns="True" x:Name="ESDataGrid" Grid.Column="1"
CommittingCellEdit="ESDataGrid_CommittingCellEdit"
CommittingRowEdit="ESDataGrid_CommittingRowEdit"
/>

Page.xaml.cs (add):

private void ESDataGrid_CommittingCellEdit(object sender, DataGridCellCancelEventArgs e)
{
    Products p = (Products)e.Row.DataContext;
    string f = e.Column.Header.ToString();
    string v = ((TextBox)e.Element).Text;
    System.Reflection.PropertyInfo pi = p.GetType().GetProperty(f);
    if (pi.PropertyType == typeof(string))
    {
        pi.SetValue(p, v, null);
    }
    else if (pi.PropertyType == typeof(int) ||  pi.PropertyType == typeof (int?))
    {
        pi.SetValue(p, int.Parse(v), null);
    }
    else e.Cancel = true;
    if (!e.Cancel)
    {
        p.esRowState = "Modified";
    }
}

private void ESDataGrid_CommittingRowEdit(object sender, DataGridRowCancelEventArgs e)
{
    Products p = (Products)e.Row.DataContext;
    if (p.esRowState == "Modified")
    {
        ESNorthwind.UpdateProductAsync(p);
    }
}

This won’t compile until we revise our service in the Web project and then update the reference to it in the Silverlight project.

INorthwind.cs (add):

[OperationContract]
void UpdateProduct(ProductsProxyStub product);

AppCode/Northwind.cs (or Northwind.svc.cs, add):

public void UpdateProduct(ProductsProxyStub product)
{
    Products prod = (Products)product.GetEntity();
    prod.Save(); // wow, that was easy..
}

Silverlight project:

linqII_three

Now the Silverlight code should compile, and if you set breakpoints both on the server’s UpdateProduct() method as well as on the new event handler in Silverlight, you should be able to watch the data model as it gets updated and sent back to the server.

Recommitting back to the server was so easy (although the reflection bits in the CommitingCellEdit event handler needs some clean-up) it’s actually a little dangerous. We can’t go live with this change on a public demo without having a nightly automated process to restore the Northwind data or else it will become unusable.

But this tutorial should have still sufficed in getting you on your feet with fetching, filtering, and updating data between Silverlight and EntitySpaces. There is a lot of design-related knowledge to be had in Silverlight, and real-world business objects to be realized in EntitySpaces, but this was a basic data discussion, so the rest is up to you.

 


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, a Mono application, 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 Friday, May 23, 2008 10:15:53 PM (Eastern Standard Time, UTC-05:00)  #    Comments [0]
 Sunday, May 04, 2008

EntitySpaces and Silverlight Demo

Part 1: Propagating EntitySpaces Data

kick it on DotNetKicks.com


Jon_Davis 
Written by Jon Davis
http://www.jondavis.net/


 

Introduction

I was asked to see how easy it would be to get EntitySpaces objects to work inside Silverlight, and to demonstrate my findings. This was a curiously interesting notion, since many have pondered whether Silverlight is a valuable runtime environment for LOB (line-of-business) applications. There are a number of reasons why Silverlight, at least in its Version2 flavor, would be very ideal for building client/server applications:

· Silverlight 2 comes with pre-built user controls ideal for business environments, such as the basic Textbox and more advanced data grid with editable cells

· Silverlight 2's user controls support two-way data binding, so that synchronization can be performed easily in either direction

· Silverlight 2's runtime is fast and fluid, using retained graphics vector-based rendering rather than redraw-at-invalidate "lazy" rendering. This results in a very responsive, clean, and professional user experience.

· XAML takes lessons learned with ASP.NET with the separation of design from programming. Properly implemented, a Silverlight application can be completely re-skinned, with its layout completely reorganized, without touching any of the user interface programming code.

· Silverlight 2 ships with built-in support for the language of your choice of: C#, VB.NET, IronRuby, IronPython, or JScript.NET. The .NET Framework itself inside of Silverlight is stripped down, but the core CLR is complete, and the target deployment environment does NOT need the .NET Framework installed with it.

· Silverlight 2 runs not only on the Windows platform and on Internet Explorer, but it also runs happily on the Macintosh and in other browsers such as Firefox and Safari. This means that Silverlight is not just Microsoft's answer to Flash for its vector graphics, it's also Microsoft's decade-long-awaited answer to Java applets, "Write once, run anywhere." An investment in Silverlight on Windows is automatically a free, bonus investment in the Mac and Firefox runtime environments.

· Silverlight 2 is also capable of communicating at runtime with web services over HTTP, making synchronization a natural programming experience without "hacking".

So here I began. My first thought was to take the EntitySpaces generated objects and put them in a shared library, then reference them in my Silverlight application. This turned out not to work as I hoped, for a few important reasons worth mentioning:

· Silverlight 2 can only reference assemblies (DLLs) that had been compiled against Silverlight's custom CLR. It cannot reference assemblies that were compiled against the normal .NET Framework (or against Mono).This is actually an opportunity for EntitySpaces, at least in its current form, because ES is built around code generation, so theoretically you could get the generated code to target Silverlight. Or so I thought, until I found...

· Silverlight 2 only "speaks" HTTP. It doesn't "speak" T-SQL, so you cannot use an ADO.NET connection, for example. There is no System.Data namespace, no ADO.NET support. While this seemed bizarre and even annoying at first, eventually I began to understand, besides for obvious security reasons, why System.Data was not present in Silverlight 2 in the current beta form: CRUD is CRUD, it doesn't matter if it's happening over ADO.NET on a SQL connection or over HTTP, as long as the job gets done.

Now I was beginning to procrastinate, because I made too many dumb assumptions. "So I guess I have to use System.Net.WebClient", I thought, "to make a manual connection to a web server, invoke a REST query I have to manually implement on the server, and then manually bring it back, parse it out, and in the end enjoy no benefit to using EntitySpaces at all?" When I finally sat down and researched what I needed to do, my jaw dropped. It’s nothing like that. In fact, it's almost silly how simple this is. The answer to the problem of the need for easy business object data synchronization lies in a wonderfully consistent new approach provisioned by Microsoft called WCF, or Windows Communications Foundation, now implemented at a basic level in Silverlight.

WCF support on Silverlight is limited to basicHttpBinding (SOAP 1.1). But that binding should suffice for most business scenarios.

The power of WCF is actually somewhat less about the underlying technology than it is about the code generation tools built into Visual Studio for building out the necessary client proxy stubs from defined interfaces at design-time. EntitySpaces' built-in WCF took me there 75% of the way, but the Silverlight SDK closed the gap very quickly by allowing me to reference my WCF service in just a couple clicks.

There was no coding of System.Net.WebClient. No manual conversion of XML to C# objects. Just beautiful EntitySpaces proxy stubs that enabled me to gather rich business object data from a server and perform quick and easy data binding against Silverlight with minimal effort.

So in this first part, I'll describe the first "baby step" of getting Silverlight to interoperate with a WCF service in order to pass valuable EntitySpaces objects into Silverlight with very little effort. Following that, in the next part I'll describe a simple scenario of fetching filtered data based on a WCF callback parameter that then takes advantage of EntitySpaces query filtering on the server, again with only a few more lines of code. Finally, if I have time, I'll continue to research and then demonstrate how to take advantage of the new client-side query support that is already available in ES 2008's latest build, adding even more flexibility to the programming user experience.

 

Run the Demo Here  ==> http://developer.entityspaces.net/ES2008/Demos/Silverlight/PartOne

Download the Source Here ==> http://www.developer.entityspaces.net/downloads/EntitySpacesSilverlightDemo.zip 


Setup

These are the prerequisites you need to walk through this demo:

· Visual Studio 2008

· EntitySpaces 2007

· Microsoft Silverlight Tools Beta 1 for Visual Studio 2008

· Northwind database
 

image

Figure 1 - Download the Silverlight tools for Visual Studio

 

Setting Up the Project and Generating Northwind Business Objects

If you’re not already familiar with EntitySpaces, we need to walk through some initial code generation so that we have some business objects to begin with.

Since nearly everything we’re doing is going to be done inside of Visual Studio, let’s start off by creating a new solution.

clip_image002[19]

Figure 2 - Start up Visual Studio and start by creating a new Project 
 

clip_image002[17]

Figure 3 - Create a Silverlight Application using .NET Framework 3.5 
 

clip_image002[1]

Figure 4 - When you create a Silverlight Application, Visual Studio prompts you to ask whether you want to create a new web to the solution or if you just want a local HTML test page. Choose to add a new Web. 
 

In my opinion, the data objects that get passed around in an application should exist in their own class library and then referenced into the application that uses them.

clip_image002[21] 

Figure 5 - Add a new project to the solution ... 

 

clip_image002[25]

Figure 6 - .. and choose Class Library as the project type. You can delete the resulting Class1 file. 

I’m going to use MyGeneration 1.3 for this demonstration. After preparing Northwind for SQL Server, I can then fire up MyGeneration.

clip_image014

Figure 7 - Open the template browser 

clip_image002[61]

Figure 8 - Expand EntitySpaces, then C#, then right-click Generated Classes Master (C#), and choose Execute. 

clip_image018

Figure 9 - I have a Visual Studio class library project set up, waiting for new code to be added to the physical directory so that I can add the files to the project after they are generated. 

clip_image020

Figure 10 - I'd like to give the Namespace a similar name as the database: NorthwindData  

clip_image022

Figure 11 - You can pick and choose your tables -- we'll use Products and Categories -- but might as well select them all. 

clip_image024

Figure 12 - On the third tab, we want to enable the WCF proxies, as highlighted in the image.  

clip_image026

Figure 13 - Click the OK button at the bottom to generate the objects  

clip_image002[27]

Figure 14 - After a moment, you may receive a confirmation message. If not, no worries, as long as your error log window isn’t filled up.  

Now I can close MyGeneration and go back to Visual Studio.

clip_image002[29]

My NorthwindData project doesn’t have anything in it yet, let’s add the newly generated files.

clip_image002[11]

Figure 15 - Click the "Show All Files" toolbar button in the Solution Explorer window.  

clip_image002[31]

Figure 16 - Now we can see our generated files. Right-click on the folder and choose "Include In Project".  

Before we can call this class library “ready”, we need to remember to reference the EntitySpaces dependency assemblies.

clip_image002[33]

clip_image002[35]

Figure 17 - You need EntitySpaces.Core and EntitySpaces.Interfaces .. 

clip_image002[37]

Figure 18 - .. as well as System.Runtime.Serialization and System.ServiceModel for WCF proxy support. 

Finally, we should also add the same references to the Silverlight_Web project, as well as EntitySpaces.Loader, EntitySpaces.LoaderMT, EntitySpaces.SqlClientProvider, EntitySpaces.Web, and EntitySpaces.Web.Design.

You will also need to add updates to your web.config for EntitySpaces to be able to read from (and later write to) the Northwind database. Here’s what I have ..

<configuration>
   <configSections>
      <sectionGroup name="EntitySpaces" type="EntitySpaces.Interfaces.esConfigSettings, EntitySpaces.Core">
      <section name="connectionInfo" type="EntitySpaces.Interfaces.esConfigSettings, EntitySpaces.Interfaces"
          allowLocation="true" allowDefinition="Everywhere" restartOnExternalChanges="true"/>
</sectionGroup>
...

...
</system.webServer>

<EntitySpaces>
    <connectionInfo default="SQL">
      <connections>
         <add name="SQL" providerMetadataKey="esDefault" sqlAccessType="DynamicSQL" provider="EntitySpaces.SqlClientProvider"
              providerClass="DataProvider"
              connectionString="Data Source=.\SQLEXPRESS;AttachDbFilename=|DataDirectory|\NORTHWND.MDF;Integrated Security=True;User Instance=True" databaseVersion="2005"/>
      </connections>
   </connectionInfo>
</EntitySpaces>

<runtime>
...


Discovering the Silverlight Tools

Before you got this far, you should have discovered that when you added the Silverlight Application, the Page.xaml file loaded right up to be edited. It might have looked like this:

clip_image042

Figure 19 - The XAML Editor view for a Silverlight Application 

This is a design canvas for a Silverlight application layout. Silverlight works like ASP.NET in that the design and the programming code are isolated from each other. There is a “code-behind” file, or a similar principle, just as with an .aspx file.

In the design (XAML) editor, there are two views on a split pane.

One view is the XAML text editor. Think of it as an HTML editor in a split pane view, such as in Microsoft Expression Web or in Dreamweaver. The only big difference here is that XAML isn’t HTML, obviously, and in fact XAML is much stricter and less forgiving of errors than HTML ever was. Even so, its power becomes evident when elements can be added to a view with minimal markup.

clip_image002[39]

Figure 20 - The XAML text editor pane.  

The other view is the Design view. Currently (at the time of this demo, the Silverlight Tools was only in Beta 1), this only works as a preview in Visual Studio. You can drag items from the toolbar to your layout, but only into the XAML text editor, not to the Design view. This isn’t the case if you have access to Blend 2.5, which at the time of this demo is currently in public Alpha (Technology Preview) and was not used for this demo at all. The design view does have some advantages, though. It provides a quick visual preview of the XAML text, and if you need to nitpick you can zoom in or out.

clip_image002[41]

Figure 21 - The Design pane.  

So let’s start adding some XAML and some logic to get, say, a data grid populated with the entire contents of the Northwind “Products” table, as provided by the EntitySpaces business objects we generated earlier.

Personally I don’t care for fixed dimensions before we even begin let’s just delete the Width and Height attributes on the <UserControl> XML node. This will make Silverlight fill the screen or else collapse to the largest object.

Next I want to add a data grid.

clip_image002[47]

Figure 22 - Drag a DataGrid control to the <Grid> content. 

I’ll add the attribute x:Name=”ESGrid”, which is the ID of the control on the page. The attribute AutogenerateColumns=”True” does what it suggests; when data is bound to the grid, the columns are automatically generated. (Without this setting, the grid would come up blank because I am not providing layout information for the columns.)

<Grid x:Name="LayoutRoot" Background="White">
    <my:DataGrid x:Name="ESGrid" AutoGenerateColumns="True"></my:DataGrid>
</Grid>

The next thing we should do is insert a “Please Wait” text block so that as we download the Products list. This is just for effect so that the user isn’t staring at a blank DataGrid or a blank screen before the data shows up. To make this effective, we should also hide the DataGrid until the data is ready.

<Grid x:Name="LayoutRoot" Background="White">
    <TextBlock Text="Please Wait .." x:Name="WaitText" VerticalAlignment="Center" HorizontalAlignment="Center" />
    <my:DataGrid x:Name="ESGrid" AutoGenerateColumns="True" Visibility="Collapsed" />
</Grid>

Now all our Silverlight app wants is some data. But before we can populate the DataGrid, we have to expose the data. So now we turn to our Silverlight_Web project.

Exposing the Data via A WCF Service

Open up the Property Pages for the Web project.

clip_image002[49]

The first thing that should come up is a list of References. Add a reference to the Northwind project
 

image

clip_image054

With Northwind added, we can now add a WCF service. Right-click on the Silverlight_Web project again and choose Add New Item…
 

clip_image056

.. and then choose WCF Service. We’ll name it “Northwind.svc”.
 

clip_image058

This generates four things:

  • An interface file defining the interface INorthwind
  • A Service (Northwind.svc) file that only acts as a stub for the code-behind C# file
  • A service implementation file (Northwind.svc.cs or App_Code/Northwind.cs) where the service code is actually going to be written, and finally
  • A set of entries in web.config that define

    • Your site’s serviceModel configuration settings such as the EndPoint configuration
    • Bindings to the Northwind service

In the Northwind service implementation, you’ll see a bogus DoWork method stub defined and exposed, like so:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.Serialization;
using System.ServiceModel;
using System.Text;

// NOTE: If you change the class name "Northwind" here, you must also update the reference to
// "Northwind" in Web.config.

public class Northwind : INorthwind
{
    public void DoWork()
    {

    }
}

You can toss this out but before you do you need to go and modify INorthwind.

Notice that INorthwind attributes itself with the ServiceContractAttribute. This identifies the interface as a WCF service interface definition. Exposed methods are attributed with OperationContractAttribute.

[ServiceContract]
public interface INorthwind
{
    [OperationContract]
    void DoWork();
}

Before we can see the Northwind project’s stuff in Intellisense, we need to build both it and the Silverlight_Web project. Right-click on the Silverlight_Web project, choose Build Web Site, and the Northwind project will build first because it is a dependency. (This is also a good time to check for errors.)

Now let’s add some code.

In INorthwind, replace “DoWork()” with “GetProducts()”, and change “void” to “NorthwindData.ProductsCollectionProxyStub”. Then go back to the service implementation file and replace “DoWork()” with “GetProducts()” again and “void” to “NorthwindData.ProductsCollectionProxyStub”.

Next, we can give the method stub some functionality.

public NorthwindData.ProductsCollectionProxyStub GetProducts()
{
    NorthwindData.ProductsCollection products = new NorthwindData.ProductsCollection();
    products.LoadAll();

    NorthwindData.ProductsCollectionProxyStub proxy = new NorthwindData.ProductsCollectionProxyStub(products);
    return proxy;
}

This will fetch all products, wrap them in a WCF-ready proxy, and spit back the proxy.

Now let’s make sure that our WCF service is functioning. Hit the Debug button in Visual Studio (while the Silverlight_Web project is selected) and when the web page comes up, navigate to Northwind.svc. You may get a prompt asking if you want to enable debugging, just say yes.

clip_image060

clip_image062

clip_image002[51]

If you can see the “Northwind Service” page, indicating “You have created a service,” you’re almost ready to start binding your service to Silverlight.

Stop the debugger before continuing.

 

Initializing EntitySpaces

Before this service will successfully work with EntitySpaces at runtime, the EntitySpaces runtime needs to be initialized to point to a database.

Right-click on the Silverlight_Web project node in Solution Explorer and choose “Add New Item...”, then select “Global Application Class” (name it the default, Global.asax). When it opens up, add the following code in Application_Start():

protected void Application_Start(object sender, EventArgs e)
{
    EntitySpaces.Interfaces.esProviderFactory.Factory = new EntitySpaces.LoaderMT.esDataProviderFactory();
}


Binding the WCF Service to Silverlight

Silverlight “speaks” WCF, but only using basicHttpBinding (SOAP 1.1). We need to update the endpoint configuration on the service so that it uses basicHttpBinding rather than the default wsHttpBinding.

Open web.config in Silverlight_Web and change wsHttpBinding to basicHttpBinding.

<system.serviceModel>
<behaviors>
    ...
</behaviors>
<services>
    <service behaviorConfiguration="NorthwindBehavior" name="Northwind">
    <endpoint address="" binding="basicHttpBinding" contract="INorthwind">
    ...

We also need to create a temporary lock on the port that our development web server (Cassini) is using. When Web projects are created within Visual Studio, a small web server loads up in the background, with a visible icon in the Windows Notification Area (or “system tray”), and the port that it uses is random. If we lock it, though, we can force Silverlight’s WCF bindings to always point to the correct web address when it calls back to the web server. This is only for debugging purposes; when deploying to production, a URL will be used literally, on port 80, as with http://www.mydomain.com/myService

To lock the web server port so that we can get a fixed reference on Silverlight, click on the Silverlight_Web project node in the Solution Explorer tree and disable the “Use dynamic ports” option.

clip_image066

Now it’s time to bind your WCF service to Silverlight. Right-click on the Silverlight project node in the Solution Explorer and choose “Add Service Reference ...”

clip_image002[53]

Then select “Discover >” and choose “Services in Solution”. The Silverlight_Web project is displayed. Expand it until you see the Northwind service, then expand that until you see the INorthwind service contract. Select the INorthwind service contract, and set the Namespace to “NorthwindClient”.
 

clip_image002[55]

Once you click on “OK”, the required assemblies for WCF support, all pre-compiled against the Silverlight runtime, are brought into Silverlight automatically.

clip_image002[57]

Great, I have my bindings. Now it’s time to populate my grid.

If you expand the Page.xaml node in the Solution Explorer, you should see the Page’s “code-behind”-ish file. Open that up and see what’s inside.

// using stuff ;
namespace EntitySpacesSilverlightDemo_Silverlight
{
    public partial class Page : UserControl
    {
        public Page()
        {
            InitializeComponent();
        }
    }
}

So we already have a constructor here where we can fire off an invocation of the WCF service. Note: All System.Net.WebClient and WCF client calls are asynchronous, so you must plan for this ahead of time whenever programming callbacks with Silverlight.

After adding “using NorthwindClient;” to the top of the file, here’s my code for within the “class Page” block:

NorthwindClient.NorthwindClient ESNorthwind;

public Page()
{
    InitializeComponent();
    ESNorthwind = new NorthwindClient.NorthwindClient();
    ESNorthwind.GetProductsCompleted += new EventHandler<NorthwindClient.GetProductsCompletedEventArgs>(NorthwindClient_GetProductsCompleted);
    LoadAllProducts();
}

private void LoadAllProducts()
{
    WaitText.Visibility = Visibility.Visible;
    ESNorthwind.GetProductsAsync();
}

void NorthwindClient_GetProductsCompleted(object sender, NorthwindClient.GetProductsCompletedEventArgs e)
{
    WaitText.Visibility = Visibility.Collapsed;
    NorthwindClient.ProductsCollection pc = e.Result;
    ESGrid.ItemsSource = pc.Collection;
    ESGrid.Visibility = Visibility.Visible;
}

Hit F5 and run, and you should see something like this:

clip_image002[59]

This is what we were designing for. We have a data-bound DataGrid, where the data derives from the same EntitySpaces business objects I perhaps already invested in elsewhere on my site or in my application, and despite a learning curve for basic configuration for WCF interop, there was actually very little code that was written by hand.


Deployment to IIS

We’re not quite done yet. Now we have to look at deployment to a production server.

Silverlight’s binding to the services is hard-coded to the URL http://localhost:11434/Northwind.svc. Silverlight is then compiled and bundled directly into the web project that hosts the WCF service. We now have a chicken-or-egg situation; both projects depend on the other. Further, EntitySpaces is hosting this demo on a shared web host that uses IIS 7 which enables WCF services natively, but WCF on IIS 7 doesn’t support HTTP endpoints through web.config without a custom service factory.

Here’s a run-down on how we got this running at: http://developer.entityspaces.net/ES2008/Demos/Silverlight/PartOne/

  1. Upload the web project files to the web server via FTP and make sure that the directory paths correctly reflect the desired URLs.
  2. In Visual Studio, with the Solution still open, choose File -> Add -> Existing Web Site..., then select FTP on the left and fill out the necessary FTP information (hostname, username, password, directory).
    Be sure to enter the exact FTP directory path to the root of the web project.
  3. We now have two copies of the same web project loaded in our solution, the local copy and the FTP-based copy. Now we need to make some configuration changes in the FTP-based copy of the project in our solution.
    • Re-link the Silverlight project. Right-click on the Project node in the Solution Explorer, choose Properties Pages, and select Silverlight Links. (If anything there, remove it now so it is empty.) Click “Add...”, ensure that your Silverlight project is available in the drop-down list for “Project to link”, and keep the Destination folder set to “/”. Click Add and then click OK. You may get some warnings that the file(s) already exist, go ahead and choose to overwrite.
    • Restore the database connection. In web.config, change the connection string at configuration/EntitySpaces/connectionInfo/connections to point to a working instance of Northwind on SQL Server on the web host.
    • Add a Northwind service factory to the project. Open App_Code/Northwind.cs and make the following changes:

      // append to the "using" declarations at the top
      using System.ServiceModel.Activation;
      using System.Configuration;

      // append inside of namespace but before or after the Northwind class block
      public class NorthwindServiceHostFactory : ServiceHostFactory
      {
          protected override ServiceHost CreateServiceHost(Type serviceType, Uri[] baseAddresses)
          {
              // Specify the exact URL of your web service
              Uri webServiceAddress = new Uri(ConfigurationManager.AppSettings["ServiceUri_Northwind"]);
              NorthwindServiceHost webServiceHost = new NorthwindServiceHost(serviceType, webServiceAddress);
              return webServiceHost;
          }
      }

      public class NorthwindServiceHost : ServiceHost
      {
          public NorthwindServiceHost(Type serviceType, params Uri[] baseAddresses)
              : base(serviceType, baseAddresses)
          { }

          protected override void ApplyConfiguration()
          {
              base.ApplyConfiguration();
          }
      }

    • Find the <appSettings> node of web.config (which might be collapsed as <appSettings/>, just change it to <appSettings><appSettings>) and add the following setting inside of it:

      <add key="ServiceUri_Northwind" value="http://developer.entityspaces.net/ES2008/Demos/Silverlight/PartOne/EntitySpacesSilverlightDemo_Silverlight_Web/Northwind.svc"/>
    • In web.config, under configuration/system.serviceModel/behaviors/serviceBehaviors, add:

      <behavior name="NorthwindFactoryBehavior" >
          <serviceMetadata httpGetEnabled="true" />
      </behavior>

    • Finally, under configuration/system.serviceModel/services, change

        <service behaviorConfiguration="NorthwindBehavior"  name="Northwind">

      .. to ..

        <service behaviorConfiguration="NorthwindFactoryBehavior" name="Northwind">

      .. and although I don’t think it’s used anyway with our factory, you might want to go ahead and change the <dns>localhost</dns> entry down in there to <dns>yourhost.com</dns>.

    • Build the solution. If build succeeds, ...
    • In the Silverlight project, expand the Service References node in the Solution Explorer and remove the NorthwindClient node by right-clicking it and choosing Delete. Then right-click on Service References and choose Add Service Reference. Click on Discover and choose Services in Solution. Select the FTP-based project. You may be asked to refine the URL, you will need to modify the default value to correctly reflect the accurate URL path to the Northwind.svc file on the live server.

    If you receive an error, open up a web browser and navigate directly to the URL of the Northwind.svc file. If it fails to show up, try to use the error message (Google is your friend) to drill down the problem. It may relate to something overlooked in the steps I described.

    1. Now right-click on the Silverlight project node in the Solution Explorer and build the project again.
    2. Finally, right-click on the web project node in the Solution Explorer and build the project again. This will pull the revised compiled Silverlight project into the hosted site.

    If you made it this far, all the hard stuff is over!! From here on out, it’s easy, blissful C# coding with EntitySpaces and a few XAML tweaks, no more configuration hassles.

    In Part 2 of this tutorial / demo, I’ll make the app a little bit more interactive, adding filters and the ability to make a few changes to the data. (It will be comparatively short compared to this part.) But now that you know how to link up ES objects to Silverlight over WCF, have fun and be safe!!



    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, a Mono application, 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 Sunday, May 04, 2008 7:59:06 PM (Eastern Standard Time, UTC-05:00)  #    Comments [0]
     Saturday, November 10, 2007

    Our next beta will sport "pure" WCF client side proxies. These proxies allow the client side of a WCF conversation to seemlessly  communicate with your heavier server proxies without the need for EntitySpaces on the client side. Our new client side proxies are very lightweight, strongly typed, and match your server side. The first scenario below showing EntitySpaces on both sides of the conversation is of course still possible, however, we have added the "EntitySpaces on the Server Only Model" which we will discuss in further detail now.

    For those interested in our new client side proxies there is a new template that you will need to run to create them. These generated proxies would be placed in a tiny class library and used by the client to communicate with your server.

    Your client side proxies will look like this, first, the collection class.

    Notice that the collection is a partial class. This will allow you to add functionality if needed. Also notice that there is no link to EntitySpaces whatsoever. You serialize from your Server Side Proxy and deserialize into your Client Side Proxies.  Now let's take a look at the entity class (which is also contained in the collection).

    Again the single entity client side proxy has no link to EntitySpaces yet you can deserialize your heavier server side proxies into these tiny lightweight proxies on the client side. Notice the partial class definition as well. The row state is maintained for you as well. All you need to do is modify your data on the client side and ship it back to the server.

    Here is a simulated converation between the server and client side proxies.

    In the above sample we are serializing from the server proxy into a string which simulates your packet being sent over the wire to the client. Next we deserialize into our lightweight client proxy, change the employee's FirstName, and then ship it back over the wire to the server to be saved. The nice thing is that when you deserialize on your server you merely grab the true Employee business object from the proxy and save it, it's so easy.

    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, November 10, 2007 10:56:44 AM (Eastern Standard Time, UTC-05:00)  #    Comments [0]
     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)  #    Comments [0]
     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)  #    Comments [0]
    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)  #    Comments [10]