Sunday, November 18, 2007

I made a blog post a while ago in a thread entitled "Microsoft ruined data binding in ASP.NET 2.0 when they dropped component support from the design surface" and thought it worthy of a follow up.

ICustomTypeDescriptor

In order to allow strongly typed entities to tack on dynamic properties (extra columns brought back via a dynamic query) for data binding in ASP.NET data grid scenarios you must implement the ICustomTypeDescriptor interface. Since our latest release (v1119) supports joins it is now common to bring back extra columns for display purposes in EntitySpaces. Well, we implemented the ICustomTypeDescriptor interface on our esEntity class and it worked perfectly in ASP.NET, however, testing then showed it broke data binding in certain Windows.Forms scenarios. Why? There is a BUG in the Microsoft.NET Framework. It's not like bugs are not found in EntitySpaces of course, this is merely an explanation of how we have arrived to this point.

We have a few ways to work around the issue. One is to use our Collection.LowLevelBind() method and the other is adding properties to your entity (not very attractive). Our esDataSource control allows you to bring back extra columns and it binds just fine, there is a "LowLevelBind" method on the esDataSource for just this scenario. This only effects ASP.NET as Windows.Forms uses ITypedList which works like a champ (in hierarchical mode also).

HierarchicalDataSourceControl

The new HierarchicalDataSourceControl binding set of interfaces proved utterly incapable of displaying a hierarchical object model. We had it "kind of working" when we realized that this new binding model only supported a single parent/child relationship. This means it cannot display the EntitySpaces hierarchical object model. So, we withdrew the implementation of this feature. Scott Piegdon has a code sample on CodeProject, you can see his response to my "Ya, Butt" comment which validated my suspicions (nice article by the way).

Summary

Again, the new Microsoft ASP.NET data binding has proven to be flawed. It is next to impossible to support both ASP.NET and Windows.Forms binding with the same codebase due to a serious bug in the .NET Framework. Also, the HierarchicalDataSourceControl implementation suffers from a lack of foresight by its designers.

And finally (whining here) this all worked in the Microsoft .NET 1.x framework, see Part One as to how we got to where we are. The same ITypedList implementation worked for both ASP.NET and Windows.Forms. However, it was swapped out for some crazy DataSource model that is clearly geared for heavily reflected architectures. Well, EntitySpaces didn't take the bait. We are still 100% reflection free. We still run in "Medium Trust" and yes, we support the DataSource control but not the HierarchicalDataSourceControl. We have a plan to work around this issue entirely in a future release.

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 Sunday, November 18, 2007 9:24:47 PM (Eastern Standard Time, UTC-05:00)  #    Comments [0]
 Sunday, October 07, 2007

I'm still not sure how useful this feature is or how it can be "tamed". I've been playing around with this via the old DataGrid control and it seems to work pretty well. However, nothing I do in the TableStyles seems to limit or control what is displayed? I simply load a collection and bind it to the DataGrid and it shows the entire hierarchical model by default and nothing I do seems to limit it. It's been a long time since I played around with hierarchical grids as IMHO they really aren't a great way to convey information.

 

 

So far this is for Windows.Forms only as all this work is done in ITypedList and ASP.NET 2.0 doesn't support this interface any longer (don't even get me started). We will be focusing next on our esDataSource control which will be receiving some major enhancements including hierarchical support and will be using it's own AppDomain to prevent it from locking DLLs. When all done, the esDataSource should be able to find your ASP.NET DLL automatically, no more browsing to it. I've downloaded one of the major Windows.Forms commerical grid suites and will be trying it out as well.

This will be in our next beta release coming soon ...  Comments welcome and encouraged, especially from the expert hierarchical "GridBinders" lurking about ...

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 Sunday, October 07, 2007 10:02:13 AM (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]