BACKGROUND
I have been working on a tool that is supposed to work in conjuction with a legacy application, and I have hit a small brick wall. I have spent the last day or so searching for clues for this, but I have had no luck.
I am trying to map a relationship between a table and multiple other tables as follows:
The parent table represents a “dictionary.” This dictionary is a list of all the database fields that can be used in ad-hoc records queries in the (horrible) legacy application. Each record holds the table and column where an item can be found, unique identfying “friendly” name, a key for use in a global value lookup table, and a flag that determines how those lookup values are pulled, and a text column that defines SQL to run to obtain lookup data if the flag value is set appropriately. The table name is [dictionary] (see below for table structure.)
The flag can have one of four values:
- FREEFORM
- STANDARD
- SYSTEM
- DYNAMIC
If the flag is set to FREEFORM, than the end user can enter any value they want. If it is any other value, then a value must be picked from a list as follows:
- STANDARD: The legacy application pulls all values from a “union all” query of two tables whose only difference is that one table is fiscal-year based, and the other is a “global” value table. These tables hold ALL lookup values for all “STANDARD” flagged dictionary records. These two tables are called [fy_lookup_values] and [lookup_values] respectively (see below for table structure)
- SYSTEM: If the friendly name in the dictionary table is “state” it pulls a list of all the states in the [state] table; if country, it does the same for the [country] table (see below for table structure)
- DYNAMIC: The lookup values are populated based on the query from dynamic SQL field described above in the dictionary table. These queries do not alias the selected columns with names even similar to the column names from the other two lookup types above. I will provide an example of one of the many tables used in these queries below.
TABLE STRUCTURES
Table [dictionary]
token int not null identity primary key
name varchar(10) not null
table_name varchar(50) not null
column_name varchar(30) not null
lookup_key varchar(10) not null
lookup_type varchar(8) not null
query_text text
Table [lookup_values]
lookup_key varchar(10) not null primary key
lookup_value varchar(20) not null primary key
lookup_description text not null
Table [fy_lookup_values]
lookup_key varchar(10) not null primary key
lookup_value varchar(20) not null primary key
lookup_description text not null
fy_year_token int not null
Table [state]
state_code varchar(4) not null primary key
state_name varchar(30) not null
Table [country]
country_code varchar(4) not null primary key
country_name varchar(50) not null
Table [banks]
bank_token int not null identity primary key
bank_name varchar(50) not null
All of the lookup value retreivals in the application grab two columns, a code and a description. The legacy application currently massages all incoming data based on column position, not name.
I cannot touch the database structure (even to add a store procedure), nor can I alter the way lookups are done, as these are all used by a few legacy applications and any changes would make management very unhappy… I wish I could, as this is only one of many things that makes my hair gray when it comes to this application. So…
My main question, I guess, is if it is possible to map these in such a way with NHibernate so that when I grab a dictionary item, it’s lookup values are filled in for me? If it is possible, how? I know that if all of the lookups were done in the same way, I could, but I don’t even know if it is possible to map based on externally obtained queries.
I hope this makes sense, as it took me a while to wrap my brain around it.
EDIT
Here are some examples of what I am trying to accomplish.
We have the following records in the [dictionary] table:
token, name , table_name, column_name, lookup_key, lookup_type, query_text
1 , gender , customer , gender , gender , STANDARD , NULL
2 , addr_st , customer , addr_st , state , SYSTEM , NULL
3 , acct_type, cust_accts, type_code , acct_type , DYNAMIC , select type_code, descr from acct_types where active = 1
So, in the legacy application, when they get pulled up, here is the SQL that is executed to pull up the lookup values.
Gender:
select lookup_value,
lookup_description
from lookup_values
union all
select lookup_value,
lookup_description
from lookup_values
where fy_year_token = @P1
Address State:
select state_code,
state_name
from state
Account Type:
select type_code,
descr
from acct_types
where active = 1
You may be able to do this by using a subclass strategy. So your lookups can inherit from an abstract class called Lookup, which you can map using a table per concrete class strategy. Your dictionary object can then have a collection of Lookups using the appropriate keys.
Due to your complex fetching strategy you will likely need to implement some kind of custom loader for each of your lookups. The caveat is that this loader is only used for Load fetching. If you want to write an HQL or criteria query against these lookups it will go against the table and the mapping. However, hopefully you don’t need to do that.