Vault of Thoughts

2006-06-01

Please visit my new blog at vaultofthoughts.net

ObjectDataSource - a working alternative

I have blogged about the problems with ObjectDataSource control and proposed two solutions neither of which was perfect. Today I will present a complete working solution. The code and .dll for this project is accessible on two external sites: here and here.


My solution deals with the problem of partially updating an object by providing a way for a developer to provide an instance of a business object on Updating event. Values read from the form are then transferred to this object. This solves the problem with properties not present on the form are reset to default because of the fact that object is constructed by the data source control. It also solves the problem with forcing the developer to provide a default constructor for each business object.


Unfortunately having to hook up to the Updating event would mean that instead of providing a default constructor, the developer would have to code the event handling method. This would not be such a big gain. Fortunately it is not necessary to provide the business object to the Update method by means of Updating event. If an object is not provided, it is retrieved using the Select method for which we already should have an implementation shouldn't we? Indeed we have, because otherwise how would we have displayed the object for editing in the first place? The only problem is that the select method should be able to accept the same number of parameters as was specified for the DataKeyNames property of the control which was bound to the data source control. This should not pose any problems since such a method will exist anyway in most cases.


Using the control is almost identical to using the ObjectDataSource control in that it requires you to specify the Select, Update, insert and Delete methods and a type name of an object providing those methods. Methods may be static or not. I wouldn't recommend using business objects for this. Rather create a separate classes to serve as a service layer for the control. Additionally the control makes a lot better use of DataObjectMethod attribute then ObjectDataSource. If a required Select, Update, Insert or Delete method name is not specified, the control will search for this method using the mentioned attribute. It will also automatically choose the method with required number of parameters. This make it super easy to build an application really fast.


The proposed solution I'm providing has one more feature which everyone should find really useful. This feature is called InternalSort and does just that - it is a generic sorting mechanism which will sort any strongly typed collection using a property specified in the sort expression. (reverse sort is also possible by adding DESC to the sort expression - ASP.NET does it automatically).


Ok, you ask: Where is the catch? One major inconvenience in using the control is that it does not have any support in form of designer. This makes it necessary work with it using the property editor. It also does not interact very well with controls such as FormView - i.e.: FormView does not generate templates given the configured data source control - like it would when used with ObjectDataSource.


If the described solution looks like it would help in developing your applications faster, feel free to use it. I only ask for one thing: a feedback. I would appreciate any kind of feedback: from "you suck" comments through "I would change this and this" to sending me free pizzas or some other stuff :-)


As a final note I have to say that while creating the control I was using the Reflector quite a lot to get to the guts of the original ObjectDataSource control and SqlDataSource. I have also used the sources of CSLA.NET by Rockford Lhotka, where there is an implementation of the DataSource control which works with the business objects of CSLA which is therefore not very generic.


kick it on dotnetkicks.com

If you liked this article why not support its author by making a donation?

14 Comments:

  • This sounds fantastic! We've been running into some of the ObjectDataSource limitations lately, and had to do all kinds of kludgy things to get around them. I will definitely try this out and give you feedback.

    By Anonymous Anonymous, at 4:39 PM  

  • I'm still fixing some minor bugs, but in what I'm doing, the control does a hell of a good job as it is :-)

    By Blogger Mikeon, at 6:37 PM  

  • Nice work. But I still don't get it how I can bind nested properties of my business objects. I thought this was one of the main aspects of the new control, or am I wrong here?

    I'd like to do the following:

    - either bind a nested property like adress.street , or
    - at least transfer the value of a form control which displays this value (using Eval("adress.street") ) to an update method.

    Could you help me out here?

    Keep up the good work,

    Marco
    marco.zierl@googlemail.com

    By Anonymous Anonymous, at 1:55 PM  

  • If you have a class Client with a property of Address of type Address you cannot use Bind("Address.Street") as you know. What I propose is to create a new class

    class ClientWithAddress
    {
    private client;
    public ClientWithAddress(Client client)
    {
    this.client = client;
    }
    private Client Client
    {
    get
    {
    if (client == null)
    {
    client = new Client();
    }
    return client;
    }
    }
    public string AddressStreet
    {
    get { return Client.Address.Street; }
    set { Client.Address.Street = value; }
    }
    public string ClientName
    {
    get { return Client.Name; }
    set { Client.Name = value; }
    }
    }

    when you have such an object then in your Select method you do something like this
    public ClientWithAddress[] GetClients()
    {
    Client[] clients = db.GetClients();
    return Array.ConvertAll<Client, ClientWithAddress>(clients, delegate(Client client) { return new ClientWithAddress(client); });
    }


    Hope this helps. If you have any other questions please feel free to ask. Check out also my new blog at:
    http://vaultofthoughts.net

    By Blogger Mikeon, at 3:18 PM  

  • Looks pretty good. My only issue during a test was its handling of GUID values passed as arguments to the SelectCommand. I get a message of "Object of type 'System.String' cannot be converted to type 'System.Guid'." The Select parameter is identified with the TypeCode of "Object," which works with the standard ASP.NET ObjectDataSource.

    By Anonymous Anonymous, at 4:00 PM  

  • Looks pretty good. My only issue during a test was its handling of GUID values passed as arguments to the SelectCommand. I get a message of "Object of type 'System.String' cannot be converted to type 'System.Guid'." The Select parameter is identified with the TypeCode of "Object," which works with the standard ASP.NET ObjectDataSource.

    By Anonymous Josh Anderson, at 4:01 PM  

  • Josh: I'm pretty sure I have fixed that issue. Be sure to check the new version at my new blog:
    http://vaultofthoughts.net/ASPNETControlsPack.aspx

    By Blogger Mikeon, at 4:08 PM  

  • Just tried that new code, but I still get the same error. I don't want to clog your comments with all the error text, but it seems to be a problem in how Reflection is invoking the select method. Again, the odd thing is that the standard ObjectDataSource seems to work.

    By Anonymous Josh Anderson, at 5:15 PM  

  • This comment has been removed by a blog administrator.

    By Blogger Mikeon, at 10:48 PM  

  • Could you please provide a complete example of how to handle updates with MyObjectDataSource? Its not clear from the 4 aspx pages.
    Thank you.

    By Anonymous Anonymous, at 11:24 PM  

  • The example is almost complete:

    [DataObjectMethod(DataObjectMethodType.Update)]
    public void Update(Client client)
    {
    // save client;
    }

    The client object you get as a parameter is filled with new values from the form. The next step would be to somehow save the client object to the database, but that depends on you particular application.

    By Blogger Mikeon, at 10:14 AM  

  • Nice stuff mike

    You can add designer support (i'm about to test this!) by adding the following attribute to your MyObjectDataSource class

    [Designer(typeof(System.Web.UI.Design.WebControls.ObjectDataSourceDesigner))]


    Cheers - Rob

    By Anonymous Rob Ensor, at 12:58 AM  

  • I've tried with the attribute and unless, I did something wrong, it didn't work for me.

    By Blogger Mikeon, at 10:24 AM  

  • Yeah you're right, i should have posted AFTER i tested it

    By Anonymous Robert Ensor, at 5:24 AM  

Post a Comment

Links to this post:

Create a Link

<< Home