TheChaseMan's Frenetic SoapBox

Always looking for better ways to do things...

ObjectDataSource, GridView, and DataKeyNames

If you are one of the poor SOBs out there trying to leverage the new ASP.NET controls that looked so cool in the demos with DataSets, but you don't use DataSets...inevitably, you will attempt to use the ObjectDataSource control with your custom business objects and run into some interesting behavior. Let's take the infamous Person class example and create a "business layer object" and bind it to an ObjectDataSource...

public class Person {

    private int _personId;

    private string _name;

    private int _age;

 

    public Person() { }

    public Person(int personId, string name, int age) {

        _personId = personId;

        _name = name;

        _age = age;

    }

 

    public int PersonId {

        get { return _personId; }

        set { _personId = value; }

    }

 

    public string Name {

        get { return _name; }

        set { _name = value; }

    }

 

    public int Age {

        get { return _age; }

        set { _age = value; }

    }   
}

<asp:GridView ID="gridViewPeople" runat="server" AllowPaging="True" AutoGenerateColumns="False"

    DataSourceID="objectDataSourcePeople">

    <Columns>

        <asp:BoundField DataField="PersonId" HeaderText="PersonId" SortExpression="PersonId" />

        <asp:BoundField DataField="Age" HeaderText="Age" SortExpression="Age" />

        <asp:BoundField DataField="Name" HeaderText="Name" SortExpression="Name" />

        <asp:CommandField ShowDeleteButton="True" ShowEditButton="True" />

    </Columns>

</asp:GridView>

 

<asp:ObjectDataSource ID="objectDataSourcePeople" runat="server" DataObjectTypeName="Person"

    DeleteMethod="DeletePerson" SelectMethod="GetPeople" TypeName="PersonDataSource"
   
UpdateMethod="UpdatePerson"></asp:ObjectDataSource>

 

public class PersonDataSource {

    public PersonDataSource() {}

 

    public List<Person> GetPeople() { ... }

 

    public void DeletePerson(Person p) { ... }

   

    public void UpdatePerson(Person p) { ... }

}

 

From that point, you run your page and the GridView will look just fine as it lists the items in your collection. All seems well in the world. Then you try to perform an update or delete and you end up with objects missing some or all of its data.

public void DeletePerson(Person p) {

    //uh oh..it's zero!

    int id = p.PersonId;

}

What you end up with is an empty Person object. However, our UpdatePerson method will end up with a Person object that contains values for Name and Age, but a zero value for PersonId. To remedy the problem, there is a DataKeyNames attribute on the GridView control that you can set. If you set the DataKeyNames property to "PersonId" this will fix the problem of the PersonId missing from our UpdatePerson method, but you will end up with a Person object that contains a PersonId value, but default values for Name and Age. If we want all of our values at run time, we can do the following:

<asp:GridView ID="gridViewPeople" runat="server" AllowPaging="True" AutoGenerateColumns="False" DataSourceID="objectDataSourcePeople"

    DataKeyNames="PersonId, Name, Age">

Perhaps this is not the best approach. I'm interested to hear from you if you have better ideas.


Digg!

posted on Sunday, November 20, 2005 8:43 AM

Feedback

# re: ObjectDataSource, GridView, and DataKeyNames 12/22/2005 6:48 AM midwest

Now, if my Person class has a property Country which returns a Country object (with properties CountryId and CountryName). How would you bind a gridview to display the list of persons (with Id, Name, Age and CountryName). The only way I could get this to work is to have the CountryName as a property on the Person class, which becomes unacceptable for more complex classes. Any ideas?

# re: ObjectDataSource, GridView, and DataKeyNames 12/22/2005 8:23 AM Sean Chase

Create a template column and use Eval(). I posted an answer to your question here...

http://www.unboxedsolutions.com/sean/archive/2005/12/22/807.aspx

Have a Merry Christmas!

# re: ObjectDataSource, GridView, and DataKeyNames 1/17/2007 4:00 PM Dharmin

Hey, I am not sure if this is what you are looking for but you could set the Data Key Names property at runtime by creating a new string array and initializing it with the three values.

ex:
GridView.DataKeyNames = new string[] {"PersonId, Name, Age"}

Cheers