3
votes

I have a table that, some of its columns are unknown at compile time. Such columns could either be of an integer value, or some Enum value. There is a table that holds all the names of such dynamic columns and also holds the column's type. This "metatable" has the following columns:

  • DynamicColumnId (Pk)
  • Name
  • TypeId (Integer / Enum, as Fk from a separate table)

Integer columns have the Name from this table, whereas Enum columns are Fk columns from a table that has that Name, with some modification (e.g. a "DynamicTable" prefix).

The only solution I could think of for this situation is using Reflection.Emit to dynamically create an Entity class and a corresponding Mapping class. Admittedly, I'm new to NHybernate / Fluent NHybernate and it seems like a relatively simple hierarchy between the tables, and so I wanted to verify my solution isn't as ugly as it initially appears...

I would also welcome solutions that completely disregard my table hierarchy, in order to effectively acheive the same results (that is, to enumerate the rows on the dynamic table, going over all the columns, with knowledge of whether they are Enums and, if they are, their possible values as well).

(Edit: Additional information re problem domain) I initially included minimal details, as to avoid Too-Much-Info related confusion. This description is much more complex, but it unravels the motives behind this design.

The application involved is designed to automate log/dump analysis. Analysis-scenarios are frequently provided by the log/dump experts and so, in order to streamline the typical process of requirements=>implementation=>verification cycle, such analysis-scenarios are implemented by the experts directly as an Iron Python code snippet, with some domain-specific constructs injected into the snippets' scope. Each snippet has a "context" for which it is relevant. An example of "context" could be "product," "version," etc... So, the snippet itself is only invoked in certain contexts - this helps simplifying the Python code by eliminating branching (you could view it as Aspect Oriented Programming, to some extent). A non-expert could use the application, with a given code-context database, to analyze a log/dump, after choosing values for the various contexts. When an expert decides that a new context is required for cataloging a certain code snippet, he could add a context, indicating the possible values it could have. Once a new context is added to the database, a non-expert that runs an analysis will be given the option to choose a value for the newly-added context. The "dynamic table" is the table that associates a code snippet with values of the various contexts (columns) that existed when the snippet was issued, plus default values for the columns that did not exist at that time.

1
Do you mean you want to modify the database schema at runtime?Paco
This is generally a bad design approach. Thus, it always depends on the situation. Could you please provide more domain specific information so that we could figure out for ourselves what you need to accomplish?Will Marcouiller
I agree with Will, I have yet to find a situation where "dynamic tables" make sense.Mauricio Scheffer
@Mauricio and Will: There are usages for dynamic tables. A database management app. like "sql server management studio" is an example of that. The problem that dynamic tables are used (or tried to be used) in places where they don't fit. This question does not describe the scenario where the dynamic tables are used, so who are we to judge?Paco
I'm not judging anything, I'm just asking because it's likely that the OP is heading for the wrong solution to his/her problem. Maybe a simpler solution can be found to his/her specific problem.Mauricio Scheffer

1 Answers

0
votes

I won't claim to fully understand your scenario, but it seems to me that you'd be better off using a key-value store such as Redis or a schema-less database like CouchDB instead of SQL. This doesn't seem to be a problem for a relational database, but if you really need to use a RDBMS I'd map NHibernate as closely as possible to the real schema (DynamicColumnId, Name, TypeId) then build whatever data structure you need on top of that.