Introduction to Typed Datasets
Note: This is part 1 of 3 articles on this subject:
- Part 2 - Typed Datasets Are Not Always The Answer
- Part 3 - Oops! Typed Datasets ARE scalable!
I'm currently developing a small winforms application for my company. It's really nothing fancy - just a data entry system connected to an Access database. In the old days, using VB6 i would have the following options as to how to implement this:
1) Create a 3-tiered application with an always-connected data layer, Business objects to handle logical Add/remove/update/Select functionality and properties, and a UI that uses the business layer
2) Create a 2-tiered application with an always-connected data layer, and a UI that uses the data layer directly and has lots of plumbing code when handling user actions
3) Create a Fully Databaound UI for the database
Option No. 1 Has the benefit of easily changing the way the application handles data logically without too much messing around, and scaling up is easy. Its main caveats are:
- Longer time to implement then the other 2
- Adding functionality entails adding the functionality in 3 different layers, meaning more overhead and more chances of errors
- It all seems very redundant for an application this small
Option No. 2 Has the benefit of less Time-To-Market coupled with, although less robust, some of the merits of option No.1. But it still requires writing plumbing code and data access code.
Option No. 3 Has the benefit of speed - but that's about it. No scalability, Changing functionality is a bitch in some cases and don't get me started on the level of UI controls that use Data binding (excluding the expensive well-known ones).Plus - It's much harder to override default binding behavior or change minutia - stuff that really matter to every user.
Enter ADO.NET
The introduction of the Dataset Object now allows me to change the way I design N-Tier applications without having to worry too much about the amount of boiler plate code for in-memory data editing. Hell, it was designed to be passed through logical and phisycal tiers - providing disconnected data and it's schema! pure (geeky) love man.
Enter the Typed DataSet
To me- typed datasets bring wealth of usability with minimal expense. It combines the ability of in-memory databases coupled with object oriented and IntelliSens'ed approached. It is arguable just how effective it is in enterprise systems (A whole different discussion) but its value is immense when it comes to create small applications like the one I mention above. I just dragged and dropped Tables from the Server Explorer onto a form or a component class - and start using data adapters to generate a typed data set. What I get in return to this 10 minute process is a full schema of the database I'm to work with -with classes that match every table, column and relationship in it. Everything is typed and in memory. Amazing.
For example - I have 2 tables Named Messages and Users which are connected by UserID and MessageID (Each user can send multiple messages).A user has ID and Name and a Message as a UserID And text .
What will be generated from the schema will be a class named by me ("MsgDataSet") which has lots of properties, but 2 of them will be MsgDataSet.Messages (of type MessagesTable) and MsgDataSet.Users (of type UsersTable). UsersTable class will containn lots of useful functions, but it is mainly comprised os UsersRow class objects. Each UsersRow object will also have properties to reflect the Table columns. So UsersRow will have an ID property of type int and a Name proeprty of type string. To Delete a User Row i'll have a UsersRow.Delete() Function. To Add a UsersRow I'll have a UsersTable.AddUsersRow() Function (with several overloads to allow adding using only property values of a new user).
One of the best parts is that if a I have a UsersRow object and i want to get all the messages for this User - I only need to write "UsersRow.GetMessageRow() and I'll get All the Messages in Messages Table owned by the UserID in question. No Selects, no nothing. Pure Generated Code - automatically! The Same Goes for a MessagesRow Object. I can call its "GetUsersRow() function to retrive its parent Row object. All this is done using Relations that were visually defined in the Dataset schema designer, which comes with .Net. This is only a tip of the iceberg.
You can do Select on Tables object, Create View of the data (just like Views in SQL server) and do filtering, sorting -whatever you like. More coolness - If you design the schema file generated (XSD file which is pure xml but has a visual designer), you can have the Table class guard you from database issues such as preserving primary keys - duplicates - default values of records - all in memory of course.
Now you can work with the data in memory. change, add, update. When you need to update the real database - just use the appropriate data adapter to Update(Dataset). If you have conflicts with the database you can see all the changed rows and accept or reject changes and re-update.
Conclusion:
The Typed Dataset that can be generated by VS.NET allows the developer to use an object oriented approach that simplifies data in-memory data management, and allows transferring logical data along with it's schema through physical and logical layers. It also allows working in a disconnected manner much more easily. On the other hand - it is fully customizable and manageable, allowing the developer to tinker with the data with a level of abstraction as deep or as shallow as desirable.
See Related Articles:
Typed Datasets Are Not Always The Answer
Oops! Typed Datasets ARE scalable!
Read more on typed datasets:
DotNetJunkies: Using Typed Datasets - Very in-depth article
MSDN Intro: Creating Typed Datasets with the Component Designer
MSDN Sample : Visual Basic .NET Code Sample: Typed Datasets