Declarative data sources - a two part invention

Onion Blog

Syndication

(Or, what the tortoise said to Achilles on declarative data sources)
 
I've been having this internal struggle with declarative data sources recently, and I thought it might help to air my thoughts and perhaps garner some feedback from some of you. [With apologies to Zeno, Lewis Carroll, and Douglas Hofstadter...
 
Achilles: The declarative data source controls in ASP.NET 2.0 greatly simplify the process of binding data to a control (look ma, no code!).
 
<asp:GridView ID="GridView2" runat="server"
        AutoGenerateColumns="True" DataKeyNames="au_id"
            DataSourceID="authorsDataSource" />
<asp:SqlDataSource ID="SqlDataSource1" runat="server"
       ConnectionString="<%$ ConnectionStrings:pubsConnectionString %>"
       SelectCommand="SELECT * FROM [authors]" />
 
Tortoise: That does seem concise, but by default the SqlDataSource maps onto a DataSet-based retrieval, which didn't really involve much code in the first place.
 
<asp:GridView ID="GridView2" runat="server"
     DataKeyNames="au_id" />
 
// in code behind
  protected void Page_Load(object sender, EventArgs e)
  {
    if (!IsPostBack)
    {
      DataSet ds = new DataSet();
      SqlDataAdapter da = new SqlDataAdapter("SELECT * FROM Authors",
          ConfigurationManager.ConnectionStrings[
                      "pubsConnectionString"].ConnectionString);
      da.Fill(ds);       
        GridView2.DataSource = ds;
      GridView2.DataBind();
    }
  }
 
Achilles: But I can switch my data source control to use IDataReader-based retrieval of data instead of a DataSet with one property!
 
<asp:GridView ID="GridView1" runat="server"
        AutoGenerateColumns="True" DataKeyNames="au_id"
            DataSourceID="authorsDataSource" />
<asp:SqlDataSource ID="authorsDataSource" runat="server"
       ConnectionString="<%$ ConnectionStrings:pubsConnectionString %>"
       SelectCommand="SELECT * FROM [authors]"
       DataSourceMode="DataReader" />
 
Tortoise: Ok, but programmatically using IDataReader didn't really involve much code either.
 
<asp:GridView ID="GridView2" runat="server"
     DataKeyNames="au_id" />
 
// in code behind
  protected void Page_Load(object sender, EventArgs e)
  {
    if (!IsPostBack)
    {
        string dsn = ConfigurationManager.ConnectionStrings[
                          "pubsConnectionString"].ConnectionString;
        using (SqlConnection conn = new SqlConnection(dsn))
        using (SqlCommand cmd =
               new SqlCommand("SELECT * FROM Authors", conn))
        {
          conn.Open();
          SqlDataReader r = cmd.ExecuteReader();
          GridView2.DataSource = r;
          GridView2.DataBind();
        }
    }
  }
 
Alright, Achilles, I'll concede that being able to perform declarative datareader-based retrieval is kind of nice. BUT - if you want to enable sorting or paging, you can't use the datareader mode.
 
Achilles: Let's talk about paging and sorting. If I switch my declarative data source back to DataSet-mode retrieval, I can, with the simple click of a mouse (or by adding two additional properties), enable both sorting and paging - and it just works!
 
<asp:GridView ID="GridView1" runat="server"
        AutoGenerateColumns="True" DataKeyNames="au_id"
            DataSourceID="authorsDataSource"
            AllowPaging="True" AllowSorting="True" />
<asp:SqlDataSource ID="authorsDataSource" runat="server"
       ConnectionString="<%$ ConnectionStrings:pubsConnectionString %>"
       SelectCommand="SELECT * FROM [authors]"
       DataSourceMode="DataReader" />
 
Tortoise: Ok, I admit that does save some code, for to do the equivalent I must not only enable the sorting and paging features of the GridView, but I must also implement handlers in response to the sorting and paging events of the GridView to properly sort and return the correct rows.
 
<asp:GridView ID="GridView2" runat="server" AllowPaging="True"
              AllowSorting="True"
              OnPageIndexChanging="GridView2_PageIndexChanging"
              OnSorting="GridView2_Sorting"
              DataKeyNames="au_id" />
 
// in code behind
  void BindAuthorsGrid()
  {
    DataSet ds = new DataSet();
    SqlDataAdapter da = new SqlDataAdapter("SELECT * FROM Authors",
        ConfigurationManager.ConnectionStrings[
                    "pubsConnectionString"].ConnectionString);
    da.Fill(ds);
    DataView dv;
    if (ViewState["sortExpr"] != null)
    {
      dv = new DataView(ds.Tables[0]);
      dv.Sort = (string)ViewState["sortExpr"];
    }
    else
       dv = ds.Tables[0].DefaultView;
 
    GridView2.DataSource = dv;
    GridView2.DataBind();
  }
 
  protected void Page_Load(object sender, EventArgs e)
  {
    BindAuthorsGrid();
  }
 
  protected void GridView2_Sorting(object sender,
                                   GridViewSortEventArgs e)
  {
    // cache in ViewState - for some reason the
    // GridView's SortExpression
    // and SortDirection properties do not retain this information
    //
    ViewState["sortExpr"] = e.SortExpression +
        (e.SortDirection == SortDirection.Ascending ?
                            " ASC" : " DESC");
 
    BindAuthorsGrid();
  }
 
  protected void GridView2_PageIndexChanging(object sender,
                                   GridViewPageEventArgs e)
  {
    GridView2.PageIndex = e.NewPageIndex;
    BindAuthorsGrid();
  }
 
Achilles: Aha - so you admit that declarative data sources are a great advance and will save developers countless hours of agonizing over code!
 
Tortoise: You're putting words in my mouth. I said that for me 'to do the equivalent' would take some code, but I'm not convinced I would want to do that in many cases. For one, all of these features are relying on capabilities of the DataSet - in fact, it strikes me that declarative data sources are merely a wizard-friendly way to integrate DataSet features into the control binding process.
 
Achilles: Well, even if that's true, there's something to be said for that.
 
Tortoise: True, it is a convenient way to expose DataSet features which may be the right choice in many cases, but it also strikes me as potentially dangerous.
 
Achilles: Dangerous? Surely you exaggerate, what could be dangerous about the DataSet?
 
Tortoise: Well, for one, the sorting feature of the DataSet is abysmally slow for any significant amount of data (same goes for the filtering capability). Databases are much more efficient at both filtering and sorting data, and their capabilities should be leveraged. Secondly, the paging mechanism you demonstrated loads all of the data into the DataSet and then the GridView simply indexes into the DataSet to display the correct rows. For large sets of data, this is potentially a huge amount of overhead.
 
Achilles: Well, you can always use the SortParameterName property of the data source and switch it to DataReader mode which would let you use your precious database to do the sorting.
 
Tortoise: You know, I tried that, and it worked fine, but I found that I was writing nearly as much code as I had done before without the data source. In addition to writing nearly the same amount of code, I had to deal with the additional abstraction of the data source which at that point seemed superfluous.
 
Achilles: You know, there are some other cool features of the data source controls that you haven't mentioned - like caching and conflict detection during updates.
 
Tortoise: Are they also dependent on the DataSet to function properly?
 
Achilles: Well, erm... yeah.
 
Tortoise: My point stands. The declarative data source model is a mechanism for exposing DataSet functionality in a declarative way for the wizard and designer.
 
Achilles: What about the ObjectDataSource - that can be bound to anything!
 
Tortoise: Let's talk about that...
 
<to be continued...>

Posted Apr 05 2005, 08:50 AM by fritz-onion
Filed under:

Comments

Craig wrote re: Declarative data sources - a two part invention
on 04-05-2005 7:13 AM
The Law of Leaky Abstractions strikes again. :)
Christophe Fouquet wrote re: Declarative data sources - a two part invention
on 04-05-2005 7:24 AM
Let's push it a little...

<asp:GenericOnLineWebSite runat="server" Id="MyStore"
DataBase="MyDataBase"
AcceptCreditCards="true"
ManageUsersForMe = "true"
SecureTheSiteForMe = "true"
SendPromoEmailsForMe = "true"
etc...

>

</asp:GenericOnLineWebSite>

I think this model of "no-code you don't need to think, just set properties" is going too far. Some decisions have to be made that will require some amount of code and sweat. Setting a DataSource property and calling DataBind() never killed anybody yet.
I'll stick with my 2 lines of code... ;-)
ok, 20 in some cases, so what? Isn't that what programmers are supposed to do anyway?

CF


haacked@gmail.com (Haacked) wrote Re: Declarative data sources - a two part invention
on 04-05-2005 8:02 AM
One thing to consider is if you're displaying a data set large enough to be a real problem, you might consider adding a parameter to the declarative data source. Who wants to use paging to get through 1000s of records. I'd rather do some sort of search or grouping.

However, for truly scalable performance sensitive apps, this type of automagical data binding never has worked and probably never will. For large result sets, I've always paged by only retrieving the records for a specific page.

Where declarative works great is when your building an internal app for use by a relatively small # of people with a relatively small resultset for any given page. Then by all means drop these suckers on a page and get going.
Mike Goatly wrote re: Declarative data sources - a two part invention
on 04-05-2005 10:35 AM
One of the things I've been hearing from MS a bit recently is that having made the .net framework so easy to use, people are "just coding" and not really caring too much about what's going on behind the scenes.

Making this sort of thing possible is ok - as long as people are 100% aware of what's being done for them - and when it's just not suitable. You know what? I seriously doubt they always will.

Fewer lines of code doesn't always equal better applications... it just means more monkeys can code...
Patrick Foley wrote re: Declarative data sources - a two part invention
on 04-05-2005 10:46 AM
Ah, nothing like a little dialectic to illustrate a point. Now THAT'S an underappreciated technique.
Keith Kelly wrote re: Declarative data sources - a two part invention
on 04-05-2005 11:40 AM
They could also just provide default sorting and paging event handlers to make it as easy to have the same functionality when binding in code...

In other words, make it as easy in code rather than trying to avoid writing code.
Sergio Pereira wrote re: Declarative data sources - a two part invention
on 04-05-2005 1:18 PM
The only thing I dispute is that I do not think that the declarative syntax is simpler than the spelled-out code. For me it's just another way of representing the logic, but instead of using the statements and one or more objects you have to use a whole bunch of properties to get the desired effect. It takes as much time (if not more) to understand all those properties and how these non-visible interact with the visible controls or with the other non-visible controls/providers/configuration. In the other hand, for someone without serious programming experience, the declarative syntax can be less frightening.
Aaron Weiker Weblog wrote ASP.NET 2.0 - A good contrast to what it really means
on 04-05-2005 2:55 PM
The Cerebral Kitchen wrote Declarative Data Sources - Fritz Onion enlightens
on 04-06-2005 5:18 AM
Jeff Ratcliff wrote re: Declarative data sources - a two part invention
on 04-06-2005 4:16 PM
It's interesting the way MS goes back and forth on the declarative approach.

Remember the Win32 way of declaring the structure of a dialog box in a resource file? Then they got rid of it for .NET in favor of creating the dialogs via code. Now I understand that a sort of XML version of a resource file will be part of Longhorn (my knowledge of the latter is very limited; I'm probably oversimplifying).

Why all the thrashing, I wonder?
anon wrote re: Declarative data sources - a two part invention
on 04-13-2005 9:54 AM
Automatic paging doesn't appear to work by just setting .DataSource = myArrayList;
Is this by design?

I can always hack up an objectdatasource to do what I want, but my collection could get generated via several methods depending on parameters so this gets a bit ugly.
Nikhil Kothari wrote re: Declarative data sources - a two part invention
on 05-17-2005 6:42 AM
I have posted some of my thoughts on this subject over on my blog at http://www.nikhilk.net/DataSourceControlThoughts.aspx.

- Nikhil
Chui Tey wrote re: C# vs S-Expressions
on 06-15-2005 5:13 PM
The original VB forms also used declarative UI language too, however, none of that is visible in the IDE, as it is meant for the exclusive use by the designer surface.

I thought that code-generation was mainly to enable users see how they can generate the same UI at runtime, plus tweak the UI for cases the designer couldn't handle. It is an attempt at one-language for everything approach.

However, the disadvantage code based UI generation is the impedance mismatch between the problem domain, which is one of nested containment of little panels vs. a linear timeline approach of describing user-interface.

Jaime Devesa wrote re: Declarative data sources - a two part invention
on 08-06-2005 3:05 AM
I think this is just a technique by Microsoft to reach all-skills developers, as the VS 2005 Express Editions are. They want to have the maximum # of programmers working with their tools/technology.
"No matter the skill you have, you can do it". I think that's the idea. The framework is big enough how to support several ways of doing the same.

If you feel better writting your code and you want to build scalable, high-performance apps, go to Code View in the IDE.

On the other hand, if you're building a personal site, or a non-pro app, go to Design Mode, drag & drop a table of your db, or use a Wizard or go to the Common Tasks menu of any of the controls...

Up to you.
Tom Pester wrote re: Declarative data sources - a two part invention
on 08-11-2005 3:40 AM
I think the big advantage of this kind of approuch is that you group all relevant information in a control.

This way you can reference it and let different controls tap into that information from with a designer.

The asp.net designer did a good job at this and let you add code where necessary.

Some real practical tests could give a defenitve anwser but I think using this model programmers will produce less defects and also go to a level of greate abstraction (= reducing complexity).

And think about the programmer who is reading/maintaining the code. Declaratice statements are a lot easier to read that goes without saying no?
Calvin wrote re: Declarative data sources - a two part invention
on 03-20-2006 10:11 PM
I don't mind to the datasourceID, I don't use it anyway.
What freak me out is the controls provide better support to datasourceid than datasource. If I set datasource manually, a lot of built-in features just disappear. Try the bi-direction sorting on a gridview. The grid just won't toggle the direction for you anymore. It's like: Use DataSourceID you idiot, or else, do everything yourself! I can only imagine that this is done on purpose or a bug. I see a lot of people are trying to manage the bi-direction sorting themselves, but SQLDataSource enjoy the built-in support. But, what the hell, who will use SQL DataSource anyway! I am wondering MS should realize that beginners are using SQLDataSource just because MS is showing them how to use it everywhere. MS never said not to use because it's a stupid idea!
Ivan wrote re: Declarative data sources - a two part invention
on 11-01-2007 8:10 AM
I just had a debate about this same topic and came to the conclusion (whether right or wrong) that the technology inherent with DataSourceID is just simply an update to that of the DataSource property and the preferred solution was to leave the older method of binding with the DataSource property intact.

What I mean is that if MS would have updated the technology behind the DataSource property to allow automatic sorting/paging, then there's no telling what effects this would have on already-existing controls that handle this behavior manually. It's in my opinion more acceptable to take the most-common route (or the lowest-common denominator) and assume that if you're setting the DataSource property, then you're already handling sorting and paging and so embedding that technology (as opposed to letting programmers handle it as they've always been doing it) could break something. So, I think MS got it right this time. Furthermore, this is not a technology that's only for designers as you can still code the 'declarative' objects and bind them using DataSourceID property thus taking advantage of automatic sorting/paging. Still, being able to do it in Design View is a clear indication that the framework is open to just about anyone.

Add a Comment

(required)  
(optional)
(required)  
Remember Me?