I've been teaching Microsoft's 2-day .NET developer training seminar for the past 3 months, and have been putting a lot of thought into how ADO.NET compares to EJB 2.
My current thought is that ADO.NET strikes me as BeanManagedPersistence
done correctly. It has a couple of features that sorta look like container managed persistence, but on closer look, they aren't the same thing.
ADO.NET has a Data
Set and a Data
Adapter class. The Data
Adapter is a composition of the 4 SQL DML statements needed to read and manipulate data in a table (select, insert, update, delete), along with a Table
Mapping for easy-read display names to table/column names. The composition of the 4 SQL queries is identical to what one usually does with ejbFindByXXX/ejbStore/ejbCreate/ejbRemove. It doesn't have ejbLoad/ejbFindByPrimaryKey because it loads data in a set oriented manner.
Adapter doesn't have the N+1 database call problem that EJB BMP has, mainly because the Data
Adapter has full responsibility for mapping to fields (Data
Rows in Data
Columns). The tradeoff was that we don't have hard-coded primitive fields, we have dynamic fields. Typed Data
Sets provide a hybrid approach because you can generate strongly typed fields, but they're still a specific kind of object in ADO.NET (i.e. Data
Table). This pattern I would liken to Property
Container in IbmSanFrancisco
or to the way an EOF object stores its data in WebObjects
, though I would suggest WebObjects
has the more elegant approach of dynamically figuring out where the data should go, in the dynamic container, or the hard coded field if it exists.
From a code simplicity perspective, ADO.NET has a Command
Builder to simplify generation of SQL for naive optimistic concurrency (one assumes it will become more advanced in later versions). Visual Studio .NET Enterprise Developer's server explorer will allow you to drag a table into your project and it will generate the SQL & ADO.NET code for full-field optimistic concurrency conflict checking. This is pretty verbose stuff, almost as much as if you wrote your own DataAccessObject
in JDBC or BeanManagedPersistence
. To those who complain about the code generation involved with EJB, I'd point to this as my way of saying "these guys do it too".
From a ContainerManagedPersistence
perspective, ADO.NET has Data
Relations for traversing tables and Constraints for cascade delete. It also has change-tracking and in-memory rollback, something an EJB 2 CMP implementation typically has. But on my browsing, it doesn't have:
- support for transparent binary M:N relationships & referential integrity, one has to traverse the DataSet graph through the associative DataTable?
- minimal update statement support, i.e. the data adapter will usually stomp on all data fields on an update. Perhaps this could be made dynamic, but it would involve manual string concatentation
- mapping to "just objects and collections". the in-memory view is purely relational. (Costin would be clapping with glee now :)
- configurative relationship setup. You need to programmatically set up your DataRelations once you've loaded the separate tables into a DataSet. There is no intuitive way to take the results of a join and split them into their component DataTables, though I'm not ruling that out as a possibility yet, maybe by futzing with the TableMappings.
I think this last point is the biggest thing that separates it from object/relational mapping. In ContainerManagedPersistence
or O/R mapping, one would map the relationships configuratively, and then also configure the "faulting" mechanisms of how objects are read from the database as the object graph is traversed. I.e. what attributes are batch-loaded, lazy-loaded, what relationships are queried using a join, or a separate query. In the ADO.NET model, all the data is read in at once, and there isn't really any "faulting", though I'm sure you could write it yourself.
ADO.NET does have, however:
More to do with how ASP.Net is implemented than ADO.Net
- transparent bi-directional XML binding, with a certain amount of inference of how relational data maps to XML and vice-versa. Custom schemas can be used within reasonable limits of affinity between the type systems.
- some sophisticated data binding with rich web controls like the DataGrid?
Add your own thoughts...
I must admit, I rarely use the DataTable/Row/Column model in my own code. I find it allows the relational model to bubble through many layers of an application, instead of hiding it. I just use the DataReader and Command.ExecuteXXX. <shrug>
ExecuteXXX is fine unless you have the need for a disconnected update model. I.e. a data cache of some sort, for example in a 2-tier C/S application. That's where Data
Set shines -- not so much in web applications. --StuCharlton
Any idea what sort of performance hit you take by using TypedDataSets?
in a real-world 2-3-tier web application? For passing between tiers (versus hand-coded data objects)
TypedDataSets? really just wrap type-casts around the code you'd normally use to access a DataSet. In my experience it's negligable between the two formats. Now, you're asking a second question -- should one use it for passing between tiers? Building an object graph of data really doesn't provide any benefits unless you start deriving data out of it or updating data within the graph. --Stu
I've been struggling with the issue of whether to use Data
Sets because of that "bubbling" issue. I haven't come to a firm conclusion yet, but I've found it helpful to consider MartinFowler
's advice in his new book, Patterns of Enterprise Application Architecture. He writes,
"Looking at .NET, Visual Studio, and the history of application development in the Microsoft world, the dominant pattern is Table Module. Although object bigots tend to dismiss this as just meaning that Microsofties don't get objects, the Table Module does present a valuable compromise between Transaction Script and Domain Model, with an impressive set of tools that take advantage of the ubiquitous data set acting as a Record Set. ...
"This doesn't mean that you can't use Domain Model, indeed you can build a Domain Model just as easily in .NET as you can in any other OO environment. But the tools don't give you the extra help that they do for Table Modules, so I'd tolerate more complexity before I felt the need to shift to a Domain Model."
It strikes me as the usual good advice from Fowler. In my domain, I'm often dealing with sets of entities. It strikes me now as more work that it's worth to split such a set up into individual objects in one layer, only to recombine them in another. -- RobinEvans?
Microsoft have written an extensive article on this topic (when to use datasets versus "real" objects) here:
There is also some related material here:
Does anyone have any experience with the pre release of ObjectSpaces
There was that really old version that I played with a bit circa 2002. It's changed significantly and there's a full release coming with VS.NET Whidbey this year. The demo at the PDC showed significant progress, though it's not quite yet at Hibernate or TOPLink levels of flexibility. --StuCharlton
CategoryComparisons CategoryDotNet CategoryJavaPlatform