by

How to Populate a ObjectDataSource from a Dataset

To use datasets for data manipulation and grid displaying is great in a SharePoint environment.  
The .NET framework offers many displaying controls for that task amongst them is the SPGridView. Grid views are excellent for presenting data because people like to see things organized in grids. it is almost natural to our eyes and project stakeholders love grids because they are like the heart and soul of a project management report.
If you are using SharePoint it is pretty straightforward to instantiate a SPGridView control and then use the datasource property to point to a dataset.
So let's say, you want to display all the team sites or site under a specific URL. you can populate a dataset with the rows and bind to the grid.

sharepoint-objectdatasource-spgridview-dataset-1
The only issue here is the network traffic. Every time you perform a postback you will force the dataset to be loaded and then the grid will just change the page displayed, but under the hood the whole dataset was there populated. If you have hundreds of sites and these are being accessed by multiple users it can potentially be using unnecessary bandwidth. ( note: There are strategies to place around this mechanism like using cache objects and persisting information in the viewstate, but we wont be discussing them here )
sharepoint-objectdatasource-spgridview-dataset-3 
 
Would not be great if we could have a out-of-the-box structure good enough to allow fetching the necessary records for a specific page?
For that we can use the ObjectDataSource control.

sharepoint-objectdatasource-spgridview-dataset-2
You can read a lot about the usages of the ObjectDataSource all over the net, but if you are like me a big fan of datasets and you have been dealign with datasets objects in many legacy applications, you want to just want to have an easy way to migrate your datasets to ObjectDataSources.
Unfortunately, the ObjectDataSource control does not have a property like objectDataSource.DataSource neither it has a LoadFromXml or Load(Dataset)...
So how do you do?
Here's how I find it: using reflection.

ObjectDataSources do not have a property to perform something like MyObjectDataSource.DataSource=MyDataSet, but it does have a constructor that allows you to parse classes and extract data methods.
So let's say you have a scenario like this in a webpart
        /// <summary>
        /// Called by the ASP.NET page framework to notify server controls that use
        /// composition-based implementation to create any child controls
        /// they contain in preparation for posting back or rendering.
        /// </summary>
        protected override void CreateChildControls()
        {
            base.CreateChildControls();
            Grid = new SPGridView
                           {
                               AutoGenerateColumns = false,
                               AllowSorting = true,
                               AllowPaging = true,
                               AllowFiltering = true,
                               PageSize = 10
                           };
 
            Grid.DataSource = MyDataSet.MyTable;
            Grid.DataBind();
        }

To convert this to an ObjectDataSource you then do this...
        /// <summary>
        /// Gets the data table for object source.
        /// </summary>
        /// <returns></returns>
        public DataSet GetDataTableForObjectSource()
        {
            // do whatever you want to do here and
            // return the table with the data
            return MyDataSet.MyTable;
        }
 
 
        /// <summary>
        /// Called by the ASP.NET page framework to notify server controls that use
        /// composition-based implementation to create any child controls
        /// they contain in preparation for posting back or rendering.
        /// </summary>
        protected override void CreateChildControls()
        {
            base.CreateChildControls();
 
            // in this constructor specify the type name, the class name and
            // the public method inside this class where the object datasource will retrieve the data
            // make it a signed assembly for security reasons.
            var edgeDataSource =
                new ObjectDataSource(
                    "MyNamespace.MyClass, MyNamespace.MyClasss, Version=1.0.0.0, Culture=neutral, PublicKeyToken=ce8ab85a8f42a5e8",
                    "GetDataTableForObjectSource") {ID = "EdgeDataSource"};
 
            Grid = new SPGridView
                           {
                               AutoGenerateColumns = false,
                               AllowSorting = true,
                               AllowPaging = true,
                               AllowFiltering = true,
                               PageSize = 10
                           };
 
            // do not use DataSource property. MUST USE DataSourceID with the control name
            Grid.DataSourceID = "EdgeDataSource";
 
            // do this before the databind
            Controls.Add(edgeDataSource);
            Controls.Add(Grid);
 
            // bind the objects and execute the call
            //specified in the ObjectDataSource constructor
            Grid.DataBind();
        }
 
Cute trick!
So there you go. To migrate, load, or populate ObjectDataSources using DataSets, all you have to do is to wrap the data returned in a public class and pass the method information to the ObjectDataSource constructor. I hope this helps you guys out there using ObjectDataSources.
Now go coding. Happy paging, happy filtering, happy caching!

By

4 comments:

  1. Hello, excuse me, if the function "GetDataTableForObjectSource" is in the same class than "CreateChildControls()", how it would the "MyNamespace.MyClass", how to write it?

    ReplyDelete
    Replies
    1. hi Lelouch, MyNamespace and MyClass are the references from the assembly that actually contains the methods to access the data. You can replace them accordingly to how you wrote your code.

      Delete
  2. I got it!!! it's so easy, just use the property of your class... this.GetType().AssemblyQualifiedName
    for example:

    var edgeDataSource =
    new ObjectDataSource(this.GetType().AssemblyQualifiedName, "GetDataTableForObjectSource") {ID = "EdgeDataSource"};

    ReplyDelete
    Replies
    1. pretty awesome, hey? :) it opens a lot of possibilities. happy if was useful for you.

      Delete