Answered by:
Are 'business objects' (as I know them) dinosaurs?

Question
-
User-2073565942 posted
OK, I'll admit I haven't exactly been keeping up with all the latest design practices, but is my concept of business objects a dinosaur already? OK, here's an example of how I would create my business objects:
The business need is that I have an Invoice which has Line Items. So I would create the following classes:
Invoice
has functions like Load(ID), Save(), Properties like DateOrdered and CustomerID, and a property called LineItems which returns my collection class
LineItems
My class that inherits from collection. Has functions like Add(oListItem), Remove(oListItem), Update(oListItem)
LineItem
a child object of Invoice, has properties like ItemID, QuantityOrdered, etc. Does not have a Save, because the parent Invoice object will take care of thatThe reason I ask is that I'm trying to bind my LineItems collection to a GridView via an ObjectDataSource, and I can find no examples of anyone who seems to be doing this. Almost everyone is passing a DataSet or Typed DataSet of the child objects to the ObjectDataSource. My ObjectDataSource definition looks like this:
<asp:ObjectDataSource ID="odsSOLineItems" runat="server" SelectMethod="GetEnumerator" DeleteMethod="Remove" InsertMethod="Add" UpdateMethod="Update" TypeName="Inventory.SOLineItems" DataObjectTypeName="Inventory.SOLineItem" />
When I googled "SelectMethod=GetEnumerator" and it came back with ZERO (zip, zilch, nada) results, I knew I was in trouble. My opinion (and I guess this is just outdated) is that using DataSets is a shortcut and doesn't give you the flexibility and full OO benefits that you get from writing your own collection and child item classes (I'm not taking a shot there, it was just my way of thinking which I'm happy to revisit given a pointer in the right direction). It seems everyone is forgoing both the LineItems and LineItem classes and just returning a DataSet of the values.
Anyway, the long and short of it is that I can't get this to work with my ObjectDataSource/GridView binding, but before I even start asking about that (I've been reading for hours now), I want to see if I'm just barking up the wrong tree before I get into specifics with the databinding issue. (but, if you must know, the error I get if I have my gridview's autogeneratecolumns set to true is:
The data source for GridView with id 'grdLineItems' did not have any properties or attributes from which to generate columns. Ensure that your data source has content.
If is set it to False and add a single bound column for my ID field, I get:
UI error loading inventory item. Error Message: 'DataBinding: 'System.Collections.ArrayList+ArrayListEnumeratorSimple' does not contain a property with the name 'ID'.
Anyway, the main question is about my data object outlook, but if you happen to have any pointers for binding my collection to the GridView, I'd love to hear that too.
Thanks,
-LV
Saturday, January 20, 2007 1:51 AM
Answers
-
User1406895847 posted
Actually what happens when you are developing a large scale of application, you have to introduce more layers for complexity/perfomace/load balancing etc for example:
1. UI
2. Business Facade
3. Business Rules, WorkFlow
4. External Service Agent, Data Access Layer
5. Database, Storage etc.
and having bind your DataAccessLayer with the entity objects looses the flexibility.
I am not sure how objectsource (Declarative Programming) solves in developing a complex UI scenerio. I find it difficult. That why i prefer imparative way thus code.
But If you are developing a small/mid size app and dont expect your app to grow. You can certainly use DataSet/ObjectSource/SQLDataSource the Declarative way.- Marked as answer by Anonymous Thursday, October 7, 2021 12:00 AM
Sunday, January 21, 2007 9:46 PM -
User-2073565942 posted
Someone reminded me I never followed up on this one, so for anyone that is using a DataObjectSource with a strongly-typed custom collection object, here is what I needed to do to get it all to work:
1) Define the object data source in my ASPX page (note SelectMethod param):
<asp:ObjectDataSource ID="odsItems" runat="server" DeleteMethod="Remove" OldValuesParameterFormatString="{0}"
SelectMethod="GetItemTransactions" TypeName="MyCompany.MyProduct.MyCommonLib.ItemTransactions, MyCommonLib, Version=2.0.0.9, Culture=neutral, PublicKeyToken=fff7203cba1586a4"
UpdateMethod="Update" InsertMethod="Add">
<DeleteParameters>
<asp:Parameter Name="ID" Type="Int32" />
</DeleteParameters>
<UpdateParameters>
<asp:Parameter Name="ID" Type="Int32" Direction="InputOutput" />
<asp:Parameter Name="Quantity" Type="Decimal" />
<asp:Parameter Name="AmountPerUnit" Type="Decimal" />
<asp:Parameter Name="LocationID" Type="Int32" />
</UpdateParameters>
<InsertParameters>
<asp:Parameter Name="ItemID" Type="Int32" />
<asp:Parameter Name="Quantity" Type="Decimal" />
<asp:Parameter Name="LocationID" Type="Int32" />
</InsertParameters>
</asp:ObjectDataSource>2) On my data object collection, I have CRUD methods decorated with DataObjectMethod attributes, and I also add a function for the collection to return itself, like so:
<DataObjectMethod(DataObjectMethodType.Select, True)> _ Public Function GetItemTransactions() As ItemTransactions 'necessary for the ObjectDataSource object's SELECT method Return Me End Function 'NOTE: Try to keep the parameter names exactly like the names of the properties they will update. This allows you to use "Bind" in the grid and have them update these params all from the same BIND name <DataObjectMethod(DataObjectMethodType.Update, True)> _ Public Sub Update(ByVal ID As Integer, ByVal LocationID As Integer, ByVal Quantity As Decimal, ByVal AmountPerUnit As Decimal) Dim bFound As Boolean = False Try For Each o As ItemTransaction In Me If o.ID = ID Then '... do stuff...
3) To the data object (the one contained in the collection), add a public default constructor, like so:
End If Next Catch ex As Exception Throw ex.GetBaseException End Try End Sub
<Obsolete("Not for use in interactive mode.", True)> _ Public Sub New() 'This default constructor is required for the ObjectDataSource 'to work with a UI component (like a gridview), but should not 'be used by anyone else (hence the attribute) 'http://codebetter.com/blogs/sahil.malik/archive/2005/12/07/135461.aspx 'http://www.lhotka.net/WeBlog/PermaLink.aspx?guid=c3293240-88c8-4f03-b4e3-01cef6ed1304 End Sub
I can't remember if that last step was necessary (it's been a while), but try it with and without and let me know what you find out.
[:)]
- Marked as answer by Anonymous Thursday, October 7, 2021 12:00 AM
Friday, November 9, 2007 4:39 PM
All replies
-
User89244710 posted
Hi LurkingVariable,Saturday, January 20, 2007 8:07 AM -
User89244710 posted
Hi LurkingVariable, sorry for the prev post i guess i am having problems with my browser
i guess the answer of your question here : http://quickstarts.asp.net/QuickStartv20/aspnet/doc/data/default.aspx
check the binding to a data access layer section and the binding section
Thanks,
Saturday, January 20, 2007 8:14 AM -
User-2073565942 posted
Hi Ahmed,
I have read all that and much much more, I can't claim it ~all~ sank in, but... I haven't seen anything that answers my question. Is the idea of building strongly-type collections of custom business objects and robust child objects, as opposed to datasets, now a no-no, and we should all just use datasets everywhere? Even the MSDN article titled "Walkthrough: Data Binding to a Custom Business Object" does not actually bind to custom data objects, it just binds to a DataSet returned from a custom business object. I've always understood the parent object, the collection object, and the child object all deserve their own custom class that allows for all the benefits and robustness of OOP (particularly encapsulation of business logic). Having a parent object handle the "AddLineItem" functionality feels wrong to me, that's what my strongly typed collection class should do. And especially having the "AddLineItem" function creating a datarow instead of a robust object definitely feels wrong. I have not been able to get my GridView to bind successfully with my ObjectDataSource that is hooked to my custom collection. I have been able to get it to work by binding the collection directly to the gridview, but I've spent days trying to do it with the ObjectDataSource because Dino Esposito tells me that using DataSource and DataBind are now 'discouraged'. So, my question is this: Is microsoft dumbing-down the development process by focusing on datasets vs. custom collections of robust child objects, or am I just a Don Quixote who is holding on to the old days and rushing head-long at windmills while missing the DataSet boat? Because I'll tell ya that I'm so frustrated that I'm about to forgo the whole databinding thing and do it by hand, which if I'd done in the first place I'd be finished by now.
Thanks, I appreciate anyone's insightful response.
-LV
Saturday, January 20, 2007 12:13 PM -
User1406895847 posted
Hi the Design you come up with is almost perfect except having the persistent logic in the same class, separate it in defferent class such as OrderDataAccess, LineItemDataAccess etc. Regarding DataSet i think it not appropriate for large scale application, good for prototype/demo. And the Last one is data binding, I actually do not prefer the declarative way which the ObjectDataSource is . I would rather prefer to bind in the following:
GridView1.DataSource = Invoice.Load("Your Invoice ID").LineItems;
GridView1.DataBind();Saturday, January 20, 2007 7:08 PM -
User-2073565942 posted
OK, if I'm a dinosaur, at least I'm not the only dinosaur:
http://www.codeproject.com/aspnet/DataTableAdapter.asp
http://codebetter.com/blogs/brendan.tompkins/archive/2006/05/11/144539.aspx
http://www.lhotka.net/WeBlog/PermaLink.aspx?guid=c3293240-88c8-4f03-b4e3-01cef6ed1304Sunday, January 21, 2007 9:19 PM -
User-2073565942 posted
Hi Amit,
Are you saying I shouldn't have a "Save" routine on my objects, I should have another helper class (like "OrderDataAccess") that I pass the object into to be saved? Seems a lot simpler, and more OO, to have the object know how to save itself rather than to create helper classes for everything? (if I've understood you correctly, that is)
Regarding using DataSource and DataBind, that's what I've resorted to, but I spent A LOT of time trying to do it with and ObjectDataSource and with the DataSourceID property because Dino told me too (http://msdn.microsoft.com/msdnmag/issues/04/08/gridview/default.aspx).
Thanks,
-LV
Sunday, January 21, 2007 9:27 PM -
User1406895847 posted
Actually what happens when you are developing a large scale of application, you have to introduce more layers for complexity/perfomace/load balancing etc for example:
1. UI
2. Business Facade
3. Business Rules, WorkFlow
4. External Service Agent, Data Access Layer
5. Database, Storage etc.
and having bind your DataAccessLayer with the entity objects looses the flexibility.
I am not sure how objectsource (Declarative Programming) solves in developing a complex UI scenerio. I find it difficult. That why i prefer imparative way thus code.
But If you are developing a small/mid size app and dont expect your app to grow. You can certainly use DataSet/ObjectSource/SQLDataSource the Declarative way.- Marked as answer by Anonymous Thursday, October 7, 2021 12:00 AM
Sunday, January 21, 2007 9:46 PM -
User-437066291 posted
Kazi,
Can you explain what classes/methods you would put in your Business Rules layer.
Say for example you have a method in your facade layer called GetContact(int contactId). How would you organize/apply the Business Rules from the Rules/Workflow layer. I just need a couple of examples to help me understand.
Thanks,
ScAndal
Friday, March 23, 2007 10:13 AM -
User-2073565942 posted
Someone reminded me I never followed up on this one, so for anyone that is using a DataObjectSource with a strongly-typed custom collection object, here is what I needed to do to get it all to work:
1) Define the object data source in my ASPX page (note SelectMethod param):
<asp:ObjectDataSource ID="odsItems" runat="server" DeleteMethod="Remove" OldValuesParameterFormatString="{0}"
SelectMethod="GetItemTransactions" TypeName="MyCompany.MyProduct.MyCommonLib.ItemTransactions, MyCommonLib, Version=2.0.0.9, Culture=neutral, PublicKeyToken=fff7203cba1586a4"
UpdateMethod="Update" InsertMethod="Add">
<DeleteParameters>
<asp:Parameter Name="ID" Type="Int32" />
</DeleteParameters>
<UpdateParameters>
<asp:Parameter Name="ID" Type="Int32" Direction="InputOutput" />
<asp:Parameter Name="Quantity" Type="Decimal" />
<asp:Parameter Name="AmountPerUnit" Type="Decimal" />
<asp:Parameter Name="LocationID" Type="Int32" />
</UpdateParameters>
<InsertParameters>
<asp:Parameter Name="ItemID" Type="Int32" />
<asp:Parameter Name="Quantity" Type="Decimal" />
<asp:Parameter Name="LocationID" Type="Int32" />
</InsertParameters>
</asp:ObjectDataSource>2) On my data object collection, I have CRUD methods decorated with DataObjectMethod attributes, and I also add a function for the collection to return itself, like so:
<DataObjectMethod(DataObjectMethodType.Select, True)> _ Public Function GetItemTransactions() As ItemTransactions 'necessary for the ObjectDataSource object's SELECT method Return Me End Function 'NOTE: Try to keep the parameter names exactly like the names of the properties they will update. This allows you to use "Bind" in the grid and have them update these params all from the same BIND name <DataObjectMethod(DataObjectMethodType.Update, True)> _ Public Sub Update(ByVal ID As Integer, ByVal LocationID As Integer, ByVal Quantity As Decimal, ByVal AmountPerUnit As Decimal) Dim bFound As Boolean = False Try For Each o As ItemTransaction In Me If o.ID = ID Then '... do stuff...
3) To the data object (the one contained in the collection), add a public default constructor, like so:
End If Next Catch ex As Exception Throw ex.GetBaseException End Try End Sub
<Obsolete("Not for use in interactive mode.", True)> _ Public Sub New() 'This default constructor is required for the ObjectDataSource 'to work with a UI component (like a gridview), but should not 'be used by anyone else (hence the attribute) 'http://codebetter.com/blogs/sahil.malik/archive/2005/12/07/135461.aspx 'http://www.lhotka.net/WeBlog/PermaLink.aspx?guid=c3293240-88c8-4f03-b4e3-01cef6ed1304 End Sub
I can't remember if that last step was necessary (it's been a while), but try it with and without and let me know what you find out.
[:)]
- Marked as answer by Anonymous Thursday, October 7, 2021 12:00 AM
Friday, November 9, 2007 4:39 PM