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]
 Friday, June 08, 2007

Venexus, Inc., a leading Business Service Provider, has released Venexus Search Engine 2.0, a new version of its full-blown search engine for web sites and portals that use the DotNetNuke Web Application Framework.

The latest release of Venexus Search also utilizes the new version of the EntitySpaces architecture, EntitySpaces 2007. EntitySpaces 2007 supports .Net Medium Trust operation. This opens the door for many users who may be using shared hosting and are currently limited by their hosting providers to medium trust environments. "EntitySpaces has allowed us to quickly absorb data schema changes and guarantees that our clients receive the quality software they demand through rigorous unit testing of both the EntitySpaces assemblies and generated code," said Scott Schecter, CTO of Venexus. "This flexibility has made EntitySpaces an invaluable tool in our development process, and is central to our agile methodologies."

Read the entire PR Newswire - Press Release ...

About Venexus, Inc.
Venexus, Inc. is a Business Service Provider (BSP) that develops and integrates business processes. Venexus provides a rare synthesis of "best of breed" technology, value-added offerings and highly desirable pricing to small and medium sized businesses throughout the United States. Venexus is a leading provider of DotNetNuke solutions and support. Venexus provides full lifecycle support of DotNetNuke with core competencies that include the planning, development, and implementation of DotNetNuke portals, skins, and modules.

For more information, please visit http://www.venexus.com

posted on Friday, June 08, 2007 11:21:56 AM (Eastern Standard Time, UTC-05:00)  #    Comments [0]
 Monday, June 04, 2007

CodeSmith and EntitySpaces 2008

EntitySpaces 2008 will greatly expand the reach of the EntitySpaces Architecture for the Microsoft .NET Framework by supporting both MyGeneration and CodeSmith. Our decision to support CodeSmith by no means indicates we are abandoning MyGeneration. MyGeneration will continue to be supported by EntitySpaces. We understand code generator loyalty, and we love MyGeneration. But, CodeSmith has its fervent followers, too. EntitySpaces 2008 will open up a new market for EntitySpaces and will give current EntitySpaces users a choice of generator.

As of EntitySpaces 2008, the EntitySpaces Architecture will be a very viable choice for the CodeSmith Community. Supporting CodeSmith will have the added advantage of allowing users to generate their EntitySpaces architecture(s) from within Visual Studio 2005 via CodeSmith’s Microsoft Visual Studio 2005 integration.

Supporting both MyGeneration and CodeSmith, as this post will outline, can be accomplished quite elegantly, and even allow for greater customization by the EntitySpaces Team.

One Architecture - Two Code Generators

The approach is straightforward. A master template will be created for each code generator. The master template will use the native user interface techniques of the given code generator to gather the user input. Next, the master template will launch the metadata sub-template which will extract the metadata using the MyGeneration MyMeta API or the CodeSmith SchemaExplorer API and create the EntitySpacesMetadata.xml file. The master template will then create an instance of the EntitySpacesPlugIn and populate it with the user’s selections and also provide it with a path to the EntitySpacesMetadata.xml file. Finally, the master template will launch a series of sub-templates just as EntitySpaces 2007 does now. The sub-templates will use only the EntitySpacesPlugIn which will run in both code generators. The only data the sub-templates will access will be the user input (which will be stored in our plug-in) and the intermediate metadata XML file. The sub-templates have no user interface nor will they call into the native code generator API. This approach will ensure that 90% or more of the code generation process will be the same regardless of what code generator is being used.

A few diagrams might help visualize how this will be accomplished.

 

 

The Metadata Sub-template creates the EntitySpacesMetadata.xml file which is then used, in conjunction with the EntitySpacesPlugin, by the common sub-templates.

 

 

Summary 

Our decision to support both MyGeneration and CodeSmith is not something that we have taken lightly. It has been seriously discussed for some time now. However, we did not want to cloud the EntitySpaces 2007 release with this announcement. Now, the time has come to let the cat out of the bag. However, EntitySpaces 2007 is by no means going to sit idle. We will be publishing a roadmap that will take ES2007 through the remainder of this year in just a few weeks. We can say now that hierarchical data binding and other very important features will make it into a follow on ES2007 release.

Move over .netTiers and make room for your new neighbor, EntitySpaces 2008.

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 Monday, June 04, 2007 6:32:40 AM (Eastern Standard Time, UTC-05:00)  #    Comments [2]
 Monday, May 28, 2007

The EntitySpaces 2007 (ES2007) Architecture for the Microsoft .NET Framework was released to production on May 28th, 2007.

The EntitySpaces team would like to thank both our customers and those evaluating EntitySpaces for working hand in hand with us on the ES2007 release. The first ES2007 beta was posted on March 4th and thus began the customer feedback / defect reporting cycle with new versions following quickly as advancements were made. You have truly helped us to make EntitySpaces 2007 a very solid offering for those developing for the Microsoft .NET Framework. We are particularly pleased with some of the mobile development that is beginning to take root. We strive hard through our forums to hear you and allow you to shape the architecture you have invested in. We also work very hard to provide high quality support on our forums and to make ourselves available to our customers.

ES2007 is a major advancement over it's predecessor (1.5.3) released on December 30th, 2006, these are just some of the new features.

EntitySpaces 2007 Major New Features:

  • Medium Trust Support
  • ASP.NET Data Binding Support via the esDataSource Control
  • Two Way Data Binding through INotifyObjectChanged
  • Very Good .NET Compact Framework Support for Mobile Devices
  • SQL CE and VistaDB support
  • Improved Transaction support via esTransactionScope
  • Improved DynamicQuery support
  • Built in paging support for Oracle, MySQL and Microsoft SQL 2005

 

For a mere $149 per developer seat you can transform your .NET development environment. Click HERE to view our pricing page. 

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 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 Monday, May 28, 2007 5:50:58 PM (Eastern Standard Time, UTC-05:00)  #    Comments [0]
 Sunday, May 20, 2007

Or how to write a complete master detail view in 2 lines of code!

In my previous article I showed how it was possible to write a complete Windows Mobile 5 application in a ridiculously small amount of code. Using the full power of the Resco controls and the simplicity of the EntitySpaces architecture this can be simplified even more.

AdvancedList

The top half of our form uses the Resco AdvancedList control. This shows a complete list of all the rows in the Surveys collection. An un-selected row displays the contents of the column 'Name', a selected row expands to display two lines and now includes the column 'Address' in the second row.

Screen Shot of the Resco AdvancedList Designer in action

The definition of this behavior is carried out at design time. Within the code all we have done is instantiated the 'Surveys' EntitySpaces collection  and attached it to the AdvancedList using the collection as the datasource for the control.

this.advancedList1.DataSource = surveys;

The cell 'Address' we have created in the 'Selected' template has its CellSource set to Address, normally this property combination in the properties dialogue is collapsed and the ColumnName and SourceType are set correctly to their appropriate values by default.

DetailView

Recalling my previous article we used the Resco DetailView control to display the full details of the record. Most of the work required to achieve this was done in 3 lines of code.

((Resco.Controls.DetailView.ItemComboBox)this.detailView1.Items["HType"]).DataSource = types;
((Resco.Controls.DetailView.ItemComboBox)this.detailView1.Items["HType"]).DisplayMember 
= HTypesMetadata.PropertyNames.Htype;
((Resco.Controls.DetailView.ItemComboBox)this.detailView1.Items["HType"]).ValueMember 
= HTypesMetadata.PropertyNames.Id;

It is in fact possible to use the design time capability of the Resco control to eliminate all but the line which does the primary datasource binding, thus reducing this to just 1 line of code!

In the screen-shot above you can see the combobox properties being set using the DetailView designer.

In conclusion we have demonstrated some of the power of EntitySpaces when used in conjunction with sophisticated but easy to use Resco Controls. This approach can obviously be extended to any third party controls that properly support data binding in this way. Remember we have built a fully functional Master-Detail application without ever writing any SQL code at all !


Robert Campbell ecommnet Robert Campbell
ecommnet ltd., Bewick House, Horsley Business Centre, Horsley, Newcastle Upon Tyne, NE15 0NY UK
www.ecommnet.co.uk  www.offexploring.com  www.autobestbuy.co.uk


posted on Sunday, May 20, 2007 4:23:34 AM (Eastern Standard Time, UTC-05:00)  #    Comments [0]
 Tuesday, May 15, 2007

This is our first user supplied EntitySpaces blog post. We hope to do more of these in the future as we have some customers doing some pretty cool stuff with the EntitySpaces architecture. A special thank you goes out to Robert Campbell of ecomment ltd. See Robert's bio at the end of this post. - The EntitySpaces Team.


In this article we’ll develop an application for a Windows Mobile ("WM5") platform device. While the application is just an example, and some would argue an incomplete one at that, we will be able to see all the necessary steps to get started with EntitySpaces (“ES”). We’ll also see how to use data source binding on a couple of 3rd party controls. You can also see a FLASH DEMO as well.

Getting Started

Prerequisites: What you need

    • Microsoft SQL Server Compact Edition
    • Microsoft SQL Server 2005
    • MyGeneration Version 1.2.0.6
    • EntitySpaces 2007 Beta v0.0507
    • Visual Studio 2005 with Windows Mobile 5 SDK installed
    • Resco AdvancedList.NET. See http://www.resco.net/products/

Create a new VS Project for Windows Mobile 5

In Visual Studio (“VS”), Clicking ‘File’ > ‘New’ should produce the New Project dialog below . I’ve selected ‘Windows Mobile 5.0 Pocket PC’, ‘Device Application’, and changed the Name to ‘Demo’.

Clicking OK at this point should result in a new project called Demo with a single blank form.

The interesting things to notice here are the default references VS implements because we’ve targeted the WM5 platform.

Create a Database

Creating a database file for use in our application is relatively simple if MS SQL Server has been installed properly.

In VS, Click the project icon in the solution tree (shown above as ‘Demo’), Right-Click, and Click ’Add’ > ’New Item...’. Select ‘Database File’ in the Add New Item dialog.

I changed the Name of the database file to Demo.sdf.

Click ‘Add’, and the standard VS Data Source Configuration Wizard pops up.

We’ll not need this as we’re going to use ES!!

Click ‘Cancel’ instead.

Double-Click the database file that appeared in the Project Solution Explorer tree.

The Server Explorer pane should now appear in your VS IDE.

If the connection to the database is closed (indicated by the little red ’x’ next to the Demo.sdf database icon), Right–Click and Clicking ’Refresh’ should restore it.

We can now build the database proper.

Right-Click on the Tables icon. Click ‘Create Table’. This will present a familiar New Table Dialog.

In this screenshot I’ve created a table called Survey and added the 5 columns.

Note the Id column is a Unique Identifier, is set as the Primary Key, is a ‘RowGuid’, and it’s practical to set the default value for the column as (newid()).

Create a second table which will be used as a related table. In this demo we’re going to use a table called HTypes (house types) for our survey.

We need to relate the two tables with some foreign key constraints. In SQL server ‘proper’ this is easily done with the relationship diagram tool in VS. However, with SQL CE or ‘Compact Edition’ as it’s now called, that’s not possible. We’ll have to do this programmatically with a TransactSQL Query.

SQL Reference (SQL Server Compact Edition) 

http://msdn2.microsoft.com/en-us/library/ms173372.aspx

I usually have to resort to the Microsoft SQL Server Management Studio to run this query as the VS component doesn’t support the ‘ALTER’ command (Anyone have any idea why? Or, indeed, why the Management Studio doesn’t support the ability to ‘Open’ tables?)

To add a constraint to the Survey table, we need to run this query:

ALTER TABLE [Survey] ADD CONSTRAINT [FK_Survey_HTypes] FOREIGN KEY([HouseType]) REFERENCES [HTypes] ([Id])

Note, in this simplified demo, I have just taken the defaults for the behavior for this constraint. A lot of this will depend on your real application. I’m no DB expert, and this is an ES demo.

At this point we have:

  • A WM5 VS project shell.
  • An SQL-CE database with tables and FK Table Constraints.

Let’s add two folders to our VS project for the files generated in the next section. Click the Project icon in the solution tree. Right-Click and Click ’Add New Folder’. Add a folder called ‘Generated’ and another called ‘Custom’.

Note the highlighted Project Folder property. You’ll need this information in the next section. The next step is to produce the ES generated classes.

MyGeneration

Start MyGeneration, and select ‘Edit’ > ‘Default Settings...’.

Click ‘Microsoft SQL CE’ from the ‘Driver’ dropdown. The easiest place to get the Connection String is by copying it from the properties dialogue of the Demo.sdf file in VS, and pasting it in the text box here. Click ‘SqlServerCe’ in the ‘DbTarget’ dropdown. Optionally, click your preferred language in the ‘Language’ dropdown, in this case, ‘C#’.

Click ‘Test Connection’ to confirm a valid connection can be established.

Click the Templates Tab of the dialogue.

All we really need to change here is the Default Output Path.

Copy the Project Directory path that was noted in the previous screenshot, and paste it to the Default Output Path here. The template will automatically find the Generated and Custom directories.

Click OK. This should start the connection to your database.

You should now be able to select and expand the MyMeta tree to show the database we have created in all its glory.

Go Generate!

Select the Template browser from the icons at the top of the left hand side of the MyGeneration IDE. Expand the EntitySpaces folder and the C# folder below that.

We’re going to run two templates:

  • Custom Classes Master (C#)
  • Generated Classes Master (C#)

We’ll Double-Click a template to load it, and click the green ‘go’ arrow to generate. Let’s start with the Custom Classes.

Custom Classes Template

Note the template has automatically selected the \Custom\ folder.

The Namespace defaults to ‘BusinessObjects’. Change this to ‘Demo’.

Ctrl-Click both tables to select them in the Select Tables window. Click the OK button/bar.

If everything goes according to plan, the output will be shown in the output tab / window.

Generated Classes Template

Double-Click on the Generated Classes Master template and Click the green ‘go’ button again.

This dialogue has two tabbed sections.

For the Basic Information tab, make the same edits as for the Custom Classes template. Again, the Output Path should be automatically filled in for you.

Click the Advanced Options tab.

On this tab we need to check the options as shown:

Important: The Ignore Schema, Ignore Catalog, and Target Compact Framework boxes need to be checked.

Click OK.

Again, if it’s worked, the output should show in the pane on the right.

We’re done with MyGeneration, either close or minimize the application.

Incorporating the generated code into the VS project

Go back to VS, and Click the ‘Refresh’ icon. Click the ‘Show All Files’ icon.

We now can see our generated files in both directories but grey’d out. As yet, they’re not part of the project.

Highlight them all using the usual Shift-Click and/or Ctrl-Click techniques. Right-click one of the highlighted files, and Click ‘Include In Project’.

Hey! Just before you go clicking ‘Build’, we need to do one more thing. Add the ES references to the project.

To do so, Click the References node in the solution tree, Right-Click and Click ‘Add Reference...’.

At this point, the current documentation suggests that the ES DLLs will be there ready to select. In my case, they were not, so Click the Browse tab and drill down to the CE directory in the place where EntitySpaces is installed. The default, and in my case, is:

C:\Program Files\EntitySpaces\Redistributables\CE

The Add Reference dialogue should look like this:

We need to Ctrl-Click Core.Ce, Interfaces.Ce, LoaderMT.Ce, and SqlClientProvider.Ce. Then, Click OK.

Your Solution tree should now look like this:

Quick! Click ‘Build’ before you collapse in anticipation!

‘Build Succeeded’

“Ah”, you cry, “It looks great, but doesn’t do anything!”

Wait… there’s more....


Adding some code!

Program.cs

The application needs to have added the medium trust loader, and, because we need a configless implementation in WindowsCE, Program.cs needs to look something like this.

using System;
using System.Collections.Generic;
using System.Windows.Forms;
using EntitySpaces.Interfaces;
using EntitySpaces.LoaderMT;

namespace Demo
{
    static class Program
    {
        /// <summary>
        /// The main entry point for the application.
        /// </summary>
        [MTAThread]
        static void Main()
        {
            // --- Manually register a connection (DO THIS ONE TIME ONLY) ---
            esConnectionElement conn = new esConnectionElement();
            conn.ConnectionString = @"Data Source=\program files\Demo\Demo.sdf;";
            conn.Name = "Demo";
            conn.Provider = "EntitySpaces.SqlClientProvider.Ce";
            conn.ProviderClass = "DataProvider";
            conn.SqlAccessType = esSqlAccessType.DynamicSQL;
            conn.ProviderMetadataKey = "esDefault";
            conn.DatabaseVersion = "2005";

            // --- Assign the Default Connection ---

            esConfigSettings.ConnectionInfo.Connections.Add(conn);
            esConfigSettings.ConnectionInfo.Default = "Demo";

            // --- Register the Loader ---

            esProviderFactory.Factory = 
new EntitySpaces.LoaderMT.esDataProviderFactory(); Application.Run(new Form1()); } } }

Form1.cs

Our ‘spec’ calls for a form that displays a grid with all the survey results, so we should add a grid. We’re going to use a 3rd party specialist grid, the Resco AdvancedList, and a panel to display the record with all its detail. Here, I’ve used the Resco DetailView.

Initializing our form

Of the many things to do to the form, the first is to add the two ES collections by dragging the icons from the toolbox to the form. Using this method, all the necessary defaults are created and end up in the designer.cs file.

I’ve also done a similar thing with the two Resco controls; the advanced list and the detail view.

I've created a method to initialize the form:

private void init()
{
    // The Grid is populated with the collection of surveys
    // just get everything; 
    if (surveys.LoadAll())
    {
        this.advancedList1.DataSource = surveys;
        this.advancedList1.Refresh();
    }
   else 
   {
        MessageBox.Show("can't load survey data");
   }
}

The record detail is displayed in a control called DetailView, We need to populate the combobox on the related field, load the collection, and bind it to the ComboBox

 

private void init()
{
    // The Grid is populated with the collection of surveys
    // just get everything;                           
    if (surveys.LoadAll())
    {
        this.advancedList1.DataSource = surveys;
        this.advancedList1.Refresh();
    }
    else 
    {
       MessageBox.Show("can't load survey data");
    }

    if (types.LoadAll())
    {
        //This sets the DataSource of the ComboBox to the collection
        ((Resco.Controls.DetailView.ItemComboBox)this.detailView1.Items["HType"]).DataSource 
= types;
((Resco.Controls.DetailView.ItemComboBox)this.detailView1.Items["HType"]).DisplayMember
= HTypesMetadata.PropertyNames.Htype;
((Resco.Controls.DetailView.ItemComboBox)this.detailView1.Items["HType"]).ValueMember
= HTypesMetadata.PropertyNames.Id; this.detailView1.Refresh(); } }

By the time we exit this method, we've done everything to populate the grid, and related fields, in the record detail display... in 12 lines of code... and NO SQL or recordset/dataset stuff to remember.


Display the Record Detail

Using the AdvancedList ("AL") to allow a user to select a record to display, we have a method showDetails. This method uses the Id of the record as its parameter. This is usually called by a row select event handler on the AL.

private void showDetails(Guid rowToEdit)
{
    s = new Survey();
    s.LoadByPrimaryKey(rowToEdit);
    this.detailView1.DataSource = null;
    this.detailView1.DataSource = s;

    this.detailView1.Refresh();
}

The method simply creates a new Survey entity, and loads it with the record data using the ES LoadByPrimaryKey() method. This binds the resulting object to the DetailView control through the assignment of the DataSource.

The ES entity ‘s’ is visible across the form.

If the user selects another row in the grid, we need to detect if they have made any changes to the current record, and save it.

private void askSave()
{
    if (s.es.IsDirty)
    {
        DialogResult result = MessageBox.Show("Save changes?", "ES Test App", 
MessageBoxButtons.YesNo, MessageBoxIcon.Question,
MessageBoxDefaultButton.Button1); if (result == DialogResult.Yes) { s.Save(); this.surveys.LoadAll(); this.advancedList1.DataSource = this.surveys; this.advancedList1.Refresh(); } } }

The 1st thing the askSave method does is to determine if the data has been altered using the property of the underlying entity. if (s.es.IsDirty)

Having determined it is, and that the user indeed wants to save it, it’s a simple matter to call the Save() method on the entity itself. After which, a call to reload the surveys collection and a refresh of the AdvancedList grid is all that’s required.


Adding a new record

Adding a new record is easy, too. I have an event attached to an AddNew menu item that looks like this.

private void AddNew_Click(object sender, EventArgs e)
{
    Survey s = new Survey();
    s.AddNew();
    showDetails((Guid)s.Id);
}

The ES AddNew() method is called to create a new entity and the Guid is passed to showDetails() to display it for editing.

Note: The AddNew() method is overloaded in the Custom Class to generate the Guid immediately rather than relying on the default mechanism in the database.

public partial class Survey : esSurvey
{
    public override void AddNew()
    {
        base.AddNew();
        this.Id = Guid.NewGuid();
    }
}

Conclusion

And... there you have it; a VS WM5 solution, an SQL Ce database, some easily generated ES BusinessObjects, a couple of Resco controls, and a few lines of code, all blended into a working application. After you've done it once, you can probably do your next project in less time than it took you to read this. Enjoy! 


 

Robert CampbellRobert Campbell was educated in Newcastle Upon Tyne University in Agricultural Engineering, worked in manufacturing for 15 years before moving into IT in the mid 80's, and worked for a variety of consulting organizations before setting up ecommnet in 1998 at the start of the dot.com boom to specialize in security and web based applications development. ecommnet is now specializing in mobile applications development and security, Web 2.0 and identity management. ecommnet are NOKIA Enterprise Solutions Certified Mobility Partners.

ecommnet ltd., Bewick House, Horsley Business Centre, Horsley, Newcastle Upon Tyne, NE15 0NY
DDI: +44 8451-740-633, T:+44 1661 854 492 F :+44 1661 854 632 M:+44 7801 270 264

posted on Tuesday, May 15, 2007 5:17:08 PM (Eastern Standard Time, UTC-05:00)  #    Comments [0]
 Thursday, May 03, 2007

First, a special thank you goes out to our customer base and to those exploring EntitySpaces 2007 via the trial version. You have been very cooperative in providing us feedback and helping us to test the EntitySpaces 2007 beta. In large part, the EntitySpaces roadmap is forged by customer feedback on our forums. On our forums not only will you receive stellar support but you can have a direct impact on the future of EntitySpaces. So, if you're not registered we encourage you to do so. EntitySpaces 1.5.3 is currently shipping, however, if you are starting a new project you will definitely want to use ES2007.


The Schedule

May  7th - Beta v0507 will be released
May 21st - Beta v0521 will be released
May 28th - EntitySpaces 2007 Officially Released


Also, we have been ensuring that no customers who have purchased EntitySpaces have their download abilities cut-off even though their one year anniversary date may have expired. No EntitySpaces customers will have their accounts expire before June 4, 2007. This will ensure that you have sufficient time to download ES2007 and even snag a possible quick release if needed, that's a pretty fair deal. We are confident that you will want to renew.


The EntitySpaces Team
--

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

posted on Thursday, May 03, 2007 10:18:20 PM (Eastern Standard Time, UTC-05:00)  #    Comments [0]
 Saturday, April 28, 2007

The esDataSource in this weekends beta can automatically handle sorting for all databases and paging for those databases which have built in paging support (SQL 2005, Oracle and MySQL). If you have been experimenting with our esDataSource we encourage you to upgrade this weekend when the new beta becomes available.

The sample ASP.NET web form below uses Northwind's Employees table and takes advantage of the built in paging capablities of EntitySpaces which in SQL 2005 uses the ROW_NUMBER function. Why Microsoft chose this syntax over the MySQL syntax for paging is hard to fathom. However, you wont have to worry about that as EntitySpaces takes care of this for you. The nice thing about the web form below is that it required almost no coding whatsoever and handles sorting and paging automatically. The TextBox is populated with the text from the EntitySpaces esDynamicQuery.es.LastQuery property each time data is fetched from the database so we can see the actual query.

The page above can also edit, delete, and save the data without writing any code as well. And more importantly, the GridView was setup entirely in design mode. The esDataSource runs just fine in Medium Trust mode as well, you'll find most DataSourceControls do not as they use heavy reflection unlike the EntitySpaces DataSource which uses NO REFLECTION.

So how did we build it?

Let's start from the beginning.

Add the esDataSource assemblies to your project

  1. EntitySpaces.Web.dll
  2. EntitySpaces.Web.Design.dll

Getting esDataSource in your Toolbox

After adding the two assemblies mentioned above (or projects if you have purchased the source code) you should be able to recompile and see the esDataSource show up on your toolbox. If you do not see it you might have to close and reopen Visual Studio. If you still do not see the esDataSource in your Toolbox you can always right mouse on your Toolbox and choose Add Tab to add a new tab. Once you have given your tab a name "right mouse" on the tab and select Choose Items  and browse to the EntitySpaces assemblies folder and click on the EntitySpaces.Web.dll. The assemblies can be found here:

The Trial Version Assemblies
C:\Program Files\EntitySpaces\EntitySpacesDemo\EntitySpacesDemo\Runtime

The EntitySpaces Developer Assemblies
C:\Program Files\EntitySpaces\Redistributables

Design Time Setup 

This is what our final page looks like in design time, notice we have our esDataSource control and a TextBox on the form. The entire page took less than 5 minutes of setup and design time.

Choosing columns

Notice in the image below that we have pointed to our class library named BusinessObjects.dll as the assembly that contains the EntitySpaces collection(s) we desire to use. You might not have to do this depending on how your project is setup. If you have a traditional .NET 1.1 type of "Project" based web solution then you will probably see your esEntityCollections without browsing to an assembly. However, if you have your esEntityCollection in a class library you will need to browse to that assembly or DLL. Reflection is used to populate this information however this reflection is in the EntitySpaces.Web.Design.dll which is not used at runtime. This brings up a tricky issue regarding new .NET 2.0 file based projects. "What assembly do we load?"  Well, for now our recommendation is for you to launch your web application without debugging it and browse to the app_code.dll. You will find it here: 

C:\WINDOWS\Microsoft.NET\Framework\v2.0.50727\Temporary ASP.NET Files\esdatabinding\8a81ff31\51684664\App_Code.fbpesify.dll

Kind of cumbersome we admit, in the above path esdatabinding is the name of the webapplication and you just kind of guess Angry on the other two, it's pretty easy though as there are only like one or two folders in those directories. It's well worth it however considering the time you can save.

Tying the GridView to the esDataSource

Right mouse on your GridView and choose "Show Smart Tag". Set the esDataSource and the DataSource and in this sample we enabled all of the other options. 

After this you can go into the normal GridView designer dialogs and reorder the columns and set other properties.

Implementing a few key esDataSource Properties and Events

If you select your esDataSource and look at the properties you can set the AutoPaging and AutoSorting properties to True. However, you will need SQL 2005, Oracle, or MySQL in order for AutoPaging to work.

Now let's hook up some events.

We only truly need two events, the esCreateEntity and esSelect. For a grid that doesn't allow editing then only the esSelect event is needed. The esPostSelect event is needed to populate the TextBox with the esDynamicQuery.es.LastQuery text which will be explained below.

First, since we have decided to use Paging we need to tell the esDataSource how many rows are in the data that we are browsing. Don't let the code below confuse you. All we are doing here is using our single entity, Employees to get the total row count and assign it the esDataSource.TotalRowCount property, we only have to do this one time. If we add or delete rows of course we should adjust it. We also set the default sorting on the grid which is important as well. Remember, using the built in paging of the database itself means we don't actually return all of the rows, we only return as many rows as we show on each page, this is why this type of paging is very fast even with mega resultsets.

protected void Page_Load(object sender, EventArgs e)
{
    if (!this.Page.IsPostBack)
    {
        Employees emp = new Employees();
        emp.Query.es.CountAll = true;
        emp.Query.es.CountAllAlias = "Count"
        if (emp.Query.Load())
        {
            esDataSrc.TotalRowCount = (int)emp.GetColumn("Count");
        }

        gridView.Sort(EmployeesMetadata.PropertyNames.LastName, SortDirection.Ascending);
    }
}

esSelect

Okay, Let's look at what is required for our esDataSrc_esSelect event which is used to provide the data for the esDataSource.

protected void esDataSrc_esSelect(object sender, esDataSourceSelectEventArgs e)
{
    EmployeesCollection coll = new EmployeesCollection();

   // Assign the esDataSourcSelectEvenArgs Collection property
    e.Collection = coll;
}

Yes, it's that easy. You can have a fully sortable, pageable grid with no more than those few lines of code.

Notice that all had to do was create our collection and assign it to the esDataSourceEventArgs.Collection property. We don't use any Where condition in this example. However, if we did need to use them we would simply use the coll.Query.Where() method to assign them. However, and this is important. If you set the esDataSource to use either AutoPaging or AutoSort you DO NOT load the collection via Query.Load() or LoadAll(). The reason is that the esDataSource itself is going to apply the OrderBy properties for sorting  and or PageSize/PageNumber properties for paging and then call Query.Load() on your collection.

esCreateEntity

If you allow editing in your grid then you need to provide the esCreateEntity event, here is our esDataSrc_esCreateEntity event.

protected void esDataSrc_esCreateEntity(object sender, esDataSourceCreateEntityEventArgs e)
{
    Employees entity = new Employees();

    if (e.PrimaryKeys == null)
        entity.AddNew();
    else
   
    entity.LoadByPrimaryKey((int)e.PrimaryKeys[0]);

    // Assign the Entity
    e.Entity = entity;
}

esPostSelect

Finally, we want to display the actual query that is run each time the esDataSource populates the grid for curiousity reasons. Since we don't call Query.Load() ourselves we need to implement the esPostSelect event and gain access the loaded collection there.

protected void esDataSrc_esPostSelect(object sender, esDataSourceSelectEventArgs e)
{
    this.txtLastQuery.Text = e.Collection.es.Query.es.LastQuery;
}

That's it. Those four methods are all that is required to make our page handle sorting, paging, editing, modifying and save the data.

Don't worry, if you're not using a database that provides built in paging you can still do paging, but you will have to provide custom paging logic, however, the esDataSourceSelectEvenArgs does provide you with the PageNumber and PageSize prefilled in, you just have to fetch the data correctly.

esDataSource "State"

The esDataSource now makes it very easy for you to deal with postbacks. There is a property named "State" which is a Hashtable that you can use to store things in (not just strings either, anything that is serializable). The nice thing is the Hashtable (esDataSource.State) lives accross postbacks. This can be handy when you desire to trap the gridView_SelectedIndexChanged event and pass the id or id(s) to another esDataSource to use, an example would be a FormView or DetailsView control.

protected void gridView_SelectedIndexChanged(object sender, EventArgs e)
{
    this.esDataSrc.State["EmployeeID"] = this.gridView.SelectedDataKey.Value;
}

This is a glimpse of what is coming in this weekends ES 2007 beta. Also, for Windows.Forms we now fully support the INotifyPropertyChanged event which you can choose on the Generated Template's "Advanced Tab".

Upon release of the official EntitySpaces 2007 there will a very complete PDF manual documenting our esDataSource control.

 

The EntitySpaces Team
--

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



posted on Saturday, April 28, 2007 10:03:08 AM (Eastern Standard Time, UTC-05:00)  #    Comments [0]
 Thursday, April 19, 2007

Topic:        Rapid DNN Module Development with EntitySpaces
Date:         Thursday, April 19, 6:30 pm
Where:
Microsoft's Las Colinas Office
LC1 Building (Right Tower)
Check in at the security desk

See Dallas DNNUG


Presentation
Learn how to quickly build custom DNN modules using the EntitySpaces architecture.  This method significantly reduces development time by automatically generating the entire module data layer using your database schema. The entity spaces data layer is designed specifically to replace the standard DNN data layer for custom module development.

About EntitySpaces
The EntitySpaces architecture is a persistence layer and business object system for the .NET 2.0 Framework. You can easily have your object model created for you in about 15 minutes.


Speaker Bio

Will Ballard is the founder and president of Dallas New Media, a web design, development, a hosting firm in Grand Prairie.  Dallas New Media has been building websites using DNN since the release of version 2. Our site credits include DNN implementations for the Dallas Stars, Fellowship Technologies, and many large churches and non-profits across the country.

 


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

posted on Wednesday, April 18, 2007 11:22:05 PM (Eastern Standard Time, UTC-05:00)  #    Comments [0]
 Saturday, April 14, 2007

Our next EntitySpaces 2007 beta is at the door. In this beta we will have Medium Trust support and a few nice tweaks concerning finding our assemblies in the Visual Studio references dialogs. The EntitySpaces assemblies can now be installed in the GAC if you so desire.


Assemblies

Before installing EntitySpaces 2007 Beta v0.0415 we want you to uninstall any prior beta and then completely delete your EntitySpaces folder if you can. We strongly advise this so that our new installation layout doesn't intermix with your current files as the folder layout has changed somewhat.

If you accept the default path during installation the EntitySpaces assemblies will be found here:

  • C:\Program Files\EntitySpaces\Redistributables
  • C:\Program Files\EntitySpaces\Redistributables\CE

The installer will also ad a few registry entries that cause the EntitySpaces assemblies to show up when you choose "Ad Reference" in Visual Studio, no need to browse. However, we do not install the EntitySpaces assemblies into the GAC during installation. You can do this of course for your installations as you roll out your application but there is no need, the ability is there of course.

Here is what you will see when you choose Add Reference in a non-Compact Framework application.


You might notice a few new assemblies, we'll get to those in a moment. The nice thing is there is no more browsing for these even though they are not installed in the GAC.

If you are working on a Compact Framework application here is what you will see when you choose "Add Reference" from within Visual Studio.
 


The ability to have your assemblies show up in the reference dialog requires that we make a registry entry. The installer has a checkbox for this that is "on" by default, you can uncheck it if you prefer to browse to your assemblies.

 

Medium Trust

You probably noticed a few new assemblies above, specifically the "loaders". The loaders enumerate through all of your registered connection entries loading the appropriate EntitySpaces Providers to support each connection. There are two forms of the loader. The non-medium trust and the medium trust version. No matter which type of loader you use you will only need to ship the data providers that you actually use. Here are the two loaders.

  • EntitySpaces.LoaderMT = medium trust (no reflection)
  • EntitySpaces.Loader     = (uses reflection, the way ES has always been up until this point)

It is our recommendation that you USE the medium trust loader. It is faster and will work in any environment. Your application will now require a one time call to assign the proper loader at program startup. Here is how we recommend that you do this in your code.

This is how our EntitySpaces Demo Application initializes the Loader (Windows Forms App)
 

namespace EntitySpacesDemo
{
   static class Program
   {
      [STAThread]
      static void Main()
      {
        
esProviderFactory.Factory =
            new EntitySpaces.LoaderMT.esDataProviderFactory();

         Application.EnableVisualStyles();
         Application.SetCompatibleTextRenderingDefault(false);
         Application.Run(new Demo());
      }
   }
}

 

For an ASP.NET the best approach is probably to add a "Global Application Class" or Global.asax file. Here is an example" 

<%@ Application Language="C#" %>

   <script runat="server">

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

      }

   </script>

If you are using the configless support (as do our DotNetNuke users) then you want to assign your loader after your connections are registered.

 

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

posted on Saturday, April 14, 2007 9:38:10 PM (Eastern Standard Time, UTC-05:00)  #    Comments [0]