Centered around the disconnected model, ADO.NET incorporates a made-to-measure API to let developers store and consume data through special in-memory containers with two key capabilities. First, they behave like real databases and provide interface and functions similar to those of a server DBMS. Second, they're serializable and implement a commit model for you to handle changes in an extremely flexible way.
Classes such as DataSet and DataTable are ideal to package data to be moved across the tiers of a distributed system. They offer advanced, database-like features such as referential integrity, optimistic locking, constraints, indexing, and filtering. They lend themselves to operate well in batch update scenarios, where client code connects to a back-end database and submits changes. DataSet objects don't know anything about databases and, in general, data providers. They're sort of super-arrays enriched with advanced and database-like features. DataSet objects can be filled programmatically with any data that can be represented in a tabular manner. Adapters are special command objects that fill DataSet and DataTable objects with the results of a query. Likewise, adapters take care of moving the contents of ADO.NET containers back to a connected database table with a compatible layout.
DataSet and DataTable are frequently used for binding data to data-bound controls. In the next chapter, we'll address this.