In my view the main difference is that TDG is database (persistance) centric, while DAO's are business / object instance centric.
TDG acts as a facade (of sorts) to the database table - and is table centric (change the table and you'd change the TDG).
DAO's are an abstract view usually represent a specific instance of an object (not the whole table, in a table centric perspective - in fact they aren't persistence centric at all); DAO's are often designed around business concepts.
TDG would be useful in situations where you simply need to build an access layer on top of a database - where the project was all about the database (getting access to it for other app's etc - say a legacy system).
DAO's would be used in more 'normal' situations where you're building a new business / logic focused solution from scratch.
TDG Example (Pseudo Code)
Your starting point would be the database, e.g: a table with 3 rows of data:
ContactsTable
--------------------
Id | Name | Ph
--------------------
01 | Bob | 192837
02 | Joe | 564738
03 | Ali | 483957
Your next step would be to build a layer of code that handled the physical data access, and the data you return would be no more and no less than what the table offers. If you have multiple tables they would be exposed separately (I think - I need to check). As a consumer of the data you'd have to join up stuff in your logic (in code outside of the TDG itself).
How your code returns the data is largely up to you - you could even use an object:
Class ContactTableRecord
[
Id
Name
Ph
]
So now you have a representation of the data in code; your app can use the data however it likes. But if the database structure changes you'd also change the code layer to match - in this case the ContactTableRecord
class. So design decisions around how the data is expose are driven by the data source.
DAO Example (Pseudo Code)
First you'd design your system around concepts - like customer, licenses, permits, purchases, endorsements, locations and so on; you'd then (probably) model relationships between those. Lets say we had some classes in our core Business Logic which we defined as:
Class Customer
[
Id
Name
Ph
Purchases
ListAllPurchases()
SendInvoice()
]
Class Purchase
[
Id
ItemDescription
Customer
DateOfPurchase
]
Up until this point we haven't accessed any data, we might not even know what our data source is going to be. If we're thinking ahead we'll abstract the data access out using Dependancy Inversion (DI).
Of central importance to DI is the interface between the BL and DAL; we might specify an interface that included something like this:
GetPurchaseDetails() - returns a PurchaseDetails object
The PurchaseDetails
object we've defined, which we intend to pass between the BL and DAL - or between our application and another application is a DAO - it's a representation of the data which makes up the Purchase and Customer. Because its center of gravity is the BL it's not constrained by the structure of the database (in fact we haven't even got to that yet - we don't need to for the DAO to exist).
// This is our DAO:
Class PurchaseDetails
[
CustomerId
Name
Ph
PurchaseId
ItemDescription
DateOfPurchase
]
For another opinion see: Table Data Gateway vs. Data Access Object