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 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;}
[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.
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:
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;}
[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 Servicestring data = wsProxyService.GetEmployee(1); XmlSerializer xs = new XmlSerializer(typeof(BusinessObjects.EmployeesProxyStub));StringReader sr = new StringReader(data); // Deserialize into our ProxyBusinessObjects.EmployeesProxyStub proxy = xs.Deserialize(sr) as BusinessObjects.EmployeesProxyStub; // Ask the proxy for the true Employees objectEmployees emp = proxy.Entity;
// Call the XmlProxy Servicestring data = wsProxyService.GetEmployee(1);
XmlSerializer xs = new XmlSerializer(typeof(BusinessObjects.EmployeesProxyStub));StringReader sr = new StringReader(data);
// Deserialize into our ProxyBusinessObjects.EmployeesProxyStub proxy = xs.Deserialize(sr) as BusinessObjects.EmployeesProxyStub;
// Ask the proxy for the true Employees objectEmployees 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);
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(); }}
[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 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;}
[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/////AQAAAAAAAAAMAgAAAD1CdXNPYmosIFZlcnNpb249MS4wLjAuMCwgQ3VsdHVyZT1uZXV0cmFsLCBQdWJsaWNLZXlUb2tlbj1udWxsDAMAAABZRW50aXR5U3BhY2VzLkNvcmUsIFZlcnNpb249MjAwNy4wLjczMC4wLCBDdWx0dXJlPW5ldXRyYWwsIFB1YmxpY0tleVRva2VuPTFjMjY4MTk5ZmIyMWJmZTgMBAAAAElTeXN0ZW0sIFZlcnNpb249Mi4wLjAuMCwgQ3VsdHVyZT1uZXV0cmFsLCBQdWJsaWNLZXlUb2tlbj1iNzdhNWM1NjE5MzRlMDg5DAUAAABOU3lzdGVtLkRhdGEsIFZlcnNpb249Mi4wLjAuMCwgQ3VsdHVyZT1uZXV0cmFsLCBQdWJsaWNLZXlUb2tlbj1iNzdhNWM1NjE5MzRlMDg5BQEAAAAZQnVzaW5lc3NPYmplY3RzLkVtcGxveWVlcw8AAAAfX0VtcGxveWVlc0NvbGxlY3Rpb25CeVJlcG9ydHNUbxpfVXBUb1RlcnJpdG9yaWVzQ29sbGVjdGlvbh5fRW1wbG95ZWVUZXJyaXRvcmllc0NvbGxlY3Rpb24qX0VtcGxveWVlVGVycml0b3JpZXNDb2xsZWN0aW9uQnlFbXBsb3llZUlEHV9PcmRlcnNDb2xsZWN0aW9uQnlFbXBsb3llZUlEBXF1ZXJ5GV9VcFRvRW1wbG95ZWVzQnlSZXBvcnRzVG8PbW9kaWZpZWRDb2x1bW5zA2Zrcxtlc0VtcGxveWVlcytQcm9wZXJ0eUNoY
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.
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.
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 LLCPersistence Layer and Business Objects for Microsoft .NEThttp://www.entityspaces.net
Page rendered at Monday, March 15, 2010 5:16:47 AM (Eastern Standard Time, UTC-05:00)
Disclaimer The opinions expressed herein are my own personal opinions and do not represent my employer's view in any way.