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.