How do I handle programmatically adding fields?
Yesterday I asked this question regarding best practices for a simple information system that I am starting to work with.
Today my client asked me if they are allowed to add fields to the main object later using the admin interface. That is, the application allows you to search a single database table (let's call it Entities), which can have various associations with other objects, but the focus is on objects.
Now, of course, the sky is the limit and it is possible.
My initial thought with this problem is to create two new tables:
Additional fields (field field code, field name, IsShownInSearchResults values, and other metadata) This is a table that will have its rows generated by the admin interface. For example, if the client later decides that they want to add the ability to track, say, the eye color of an Entity, they will create an additional filter with an Eye Color field.
Additional FieldData strong> (FieldDataID PK, EntityID FK, FieldID FK, FieldValue) This is a table that associates objects with their respective values for any additional fields added by the client. For example, with our eye color example, if we have two Entities (EntityIDs 3 and 4) at the time of adding a field, and the new additionalFieldField has a field ID of 1, then there really is no eye color data associated with the objects, then the client can choose , add the eye color "Blue" to Entity 3 and we add a line to AdditionalFieldData like this: (PC autogenerated, 3, 1, "Blue").
Since I want to find them easily, I just require all additional fields to have string values.
Following the approach I posted in a previous question, I would use Linq-To-SQL with a query similar to the following to get information when a user searches (of course, the filtering logic would be more complex in practice):
var results = from s in db.Stuff
where (s.Name.Contains(textFilter) ||
s.Title.Contains(textFilter))
select s;
I would modify the query to look something like this:
var results = from s in db.Stuff
where (...existing filter logic...) ||
s.AdditionalFieldData.Any(afd => afd.FieldName.Contains(textFilter))
select s;
So my question is: is this reasonable? Is there a better solution I missed? Are there any implications of this approach that I should be aware of?
(Please excuse my stupid IDs, its early for me :)
a source to share
I'm not a LINQ expert, but from a database design standpoint, what you suggest seems to me to be great.
An alternative that I've seen several times is to have a whole bunch of "extra" fields defined in the Entities table that users can enable / disable through the admin interface. This way you get some database performance (due to fewer connections), but you have to choose how many of those backing fields you want, and most of the time you end up with large, mostly empty tables.
Oh, and you can safely assume that if you want to add N spare fields, your users will want N + 1; -)
a source to share