Trictionary - Good Idea?

10 views
Skip to first unread message

Joe Enos

unread,
Dec 18, 2008, 1:40:32 AM12/18/08
to DotNetDevelopment, VB.NET, C# .NET, ADO.NET, ASP.NET, XML, XML Web Services,.NET Remoting
I've got a need to have a dictionary that returns more than one object
for a given key. There are a few ways of doing this that I could
think of, but they weren't really elegant and/or reusable:

1) Build a custom container or extended class containing the two
objects, then do a regular Dictionary<KeyType, Container>.
2) Have a Dictionary<KeyType, KeyValuePair<ValueType1, ValueType2>>.

I had an idea for something new, but I don't know if this is
necessarily a good idea, or if it's been done before - Please let me
know if you have an opinion on this:

class Trictionary<TKey, TValue1, TValue2>

It would contain a private Container<TValue1, TValue2> class (that
stores the two values) and a Dictionary<TKey, Container>, both behind
the scenes.

It would have methods like the following - basically wrappers around
the private Dictionary:
Set(TKey key, TValue1 value1, TValue2 value2) {}
Remove(TKey key) {}
Clear() {}
ContainsKey(TKey key) {}
Get(TKey key, out TValue1 value1, out TValue2 value2) {}
I don't like the idea of "out" parameters, but I couldn't think of any
other way to return two values, without resorting to something like an
F# Tuple.

You could iterate and get a series of KeyDualValuePair<TKey, TValue1,
TValue2> objects (a custom object, instead of the normal KeyValuePair
that you could get by iterating a Dictionary).

Does anyone have any experience doing something like this? If you
have any ideas or insight into this technique, I'd appreciate it.

Thanks

Joe

Charles A. Lopez

unread,
Dec 18, 2008, 2:17:12 AM12/18/08
to DotNetDe...@googlegroups.com
Can we see some sample data?
--
Charles A. Lopez
charle...@gmail.com

Bachelor of Arts - Computer Science
New York University

Registered Microsoft Partner

New York City, NY

Joe Enos

unread,
Dec 18, 2008, 9:20:58 AM12/18/08
to DotNetDevelopment, VB.NET, C# .NET, ADO.NET, ASP.NET, XML, XML Web Services,.NET Remoting
Sample (this isn't exactly what I have in real life, but it's the same
concept - so forgive me if the logic doesn't sound right) - sorry if
this gets a little long-winded:

Suppose I have a class called Account that represents a record in our
Account database table - the primary key is AccountId, and there are
50 accounts - these accounts do not change. There's a table named
Vehicle, and a corresponding Vehicle class, with an AccountId column/
property. There's a one-to-many relationship, so each account can
have many vehicles, and that number can change daily.

Suppose I have a table called Transaction - each transaction belongs
to a particular account (so it has an AccountId foreign key column).
I have a daily process that runs through all of the new transactions,
and needs to know information about the corresponding account, and
also the count of vehicles belonging to that account. During this
particular process, it is safe to assume that the vehicle count per
account will not change (it only changes once per day, and not at the
same time as the transaction processing). So I have to loop through
each transaction, look up the corresponding account, and get the count
of vehicles. Here are some possibilities.

1) For each transaction, make a database call to the Account table to
look up the information, and a second call to the Vehicle table to
retrieve a count of vehicles per account.
2) For each transaction, make a single database call to the Account
table with a join to the Vehicle table to retrieve the count at the
same time, and store the results in a custom object.
3) Actually make a column on the Account table with the count, and use
triggers or other techniques to keep this column updated.
4) Make two Dictionaries - one for <AccountId, Account> and one for
<AccountId, VehicleCount> - pre-populate these two dictionaries and
use both of them when I need the information for each transaction.
5) Make a custom AccountContainer that contains an Account object and
an integer representing the count, then pre-populate a Dictionary of
<AccountId, AccountContainer>.
6) Make a custom AccountEx object that derives from Account, and
contains the integer representing the count, then pre-populate a
Dictionary of <AccountId, AccountEx>.
7) Make a Trictionary of <AccountId, Account, VehicleCount>.

My goal is to make the process as fast as possible, so I don't want to
make database calls with every transaction, especially not to get the
count of the Vehicle table - that table is so large that a count by Id
takes a long time (nearly a second). I would prefer not to even call
the Account table with each transaction, since even though it's a
small table, it's still faster to query the in-memory dictionary (the
result-set of accounts is so small that it's no big deal to store in
memory. And I really don't want to add the "count" column to the
account table - I prefer not to have data about data inside real data.

Any of these solutions will work - #5 or #6 would be the best
performance, but that means I'd need to define a new Type each time I
wanted to use this technique. The Trictionary's goal would be to
remove this need by having that generic type under the sheets,
allowing me to focus on the work. A code sample:


Trictionary<int, Account, int> myTrictionary = new Trictionary<int,
Account, int>();

/* This would do the work one time of retrieving both the full
accounts and the vehicle counts from the database. It's ok if this
takes a long time - a one-time load at the beginning of the process is
no big deal, as long as each individual transaction doesn't take a
long time - there are only 50 accounts, but thousands of transactions
daily. */
foreach (Account account in GetAccounts())
{
myTrictionary.Set(account.AccountId, account, GetVehicleCount
(account.AccountId));
}

foreach (Transaction t in GetNewTransactions())
{
int accountId = t.AccountId;
Account account;
int vehicleCount;
myTrictionary.Get(accountId, out account, out vehicleCount);
// I now have the account and vehicle count for this particular
transaction, retrieved from memory.
}

This is only one specific usage - I'm sure there are plenty of other
situations where returning two objects from a Dictionary can be
useful.

Thanks

Joe

On Dec 18, 12:17 am, "Charles A. Lopez" <charlesalo...@gmail.com>
wrote:
> charlesalo...@gmail.com

Cerebrus

unread,
Dec 18, 2008, 1:58:27 PM12/18/08
to DotNetDevelopment, VB.NET, C# .NET, ADO.NET, ASP.NET, XML, XML Web Services,.NET Remoting
I'm sorry, Joe, I did not have time to read through your entire post
but on reading the first line, the first thing to pop into my mind was
NVC - NameValueCollection.

This would be appropriate only if my preliminary understanding of your
scenario is: One Key - Multiple Values.

Joe Enos

unread,
Dec 18, 2008, 3:02:43 PM12/18/08
to DotNetDevelopment, VB.NET, C# .NET, ADO.NET, ASP.NET, XML, XML Web Services,.NET Remoting
Thanks for the idea - I wasn't aware of that object, and it looks like
it has uses...

But I don't think this will work for me, since I need different object
types - NVC is for an integer key and a string key, and a string value
only, if I'm reading everything right. My keys and values can be
various types, and I'll have two values for the same key, instead of
two keys that go together (not sure if that really makes a difference,
but semantically they're different).
Reply all
Reply to author
Forward
0 new messages