Great stuff. Thanks for doing it.
I did discover one problem: The PrimaryKeys property is not getting loaded correctly. This is because in GetTableKeys you are only returning the foreign keys that exist on the given table, when in fact you also have to return the foreign keys that
point to the given table.
For example, let's say you have something like this:
TABLE: Contacts
COLUMNS: ContactID, Name, Address, Email
TABLE: Phones
COLUMNS: PhoneID, ContactID, Type, Number
where Phones.ContactID references Contacts.ContactID. Right now, your GetTableKeys(Phones) is returning a single row describing the relationship. That's correct. However, GetTableKeys(Contacts) should be returning
the exact same row to describe the same relationship.
In my own version, I've taken what you did for GetTableKeys and encapsulated it into a private helper function (GetMyTableKeys). Then I created another private helper function (GetOthersTableKeys) that does the same, but looks for foreign keys pointing back at my table, and used that to add to your list.
Knowing all this, I'm sure you can whip together your own version of this, but if you'd like my code I'll be happy to post it as well.
Thanks again for doing all the heavy lifting.