The recently released Sitefinity 4.0 BETA includes a new Form Builder. This form builder enables anyone to create web-based forms without writing a single line of code. This is done using user-friendly drag & drop form elements and layouts.
This is great, but there is a lot more to this story. Once these forms are created, Sitefinity is doing some incredible things under the hood. To illustrate this, I’m going to create a new form:
Then create a basic Contact Us form (name, email, priority, message):
And publish. We now have a new form. Piece of cake!
Great! But what just happened?
Behind the scenes, Sitefinity created a brand new database table specifically for this form.
All new responses to this form will be persisted in this custom table.
By the way, if you’re wondering where those column names came from, check the Advanced Properties for the form element that was dropped onto the form.
Why is this good?
Creating new tables for new forms is interesting, but why is this good? Alternately, what is the alternative to creating new tables for new forms. To address this, I’m going to use an analogy.
Imagine that you have 1,000 marbles, 1,000 rocks & 1,000 legos.
The marbles, rocks and legos all vary in color and size.
All 3,000 of these items are then thrown into a big container. Then comes a question:
How many blue marbles are in the container?
Answering this question requires you to separate the marbles from the items that aren’t marbles. Once separated, you need to count the blue marbles. If I turn around and ask you to count yellow legos, once again you need to first eliminate everything that isn’t a lego. Valuable time is being wasted filtering items that aren’t related to the question.
This entire task would be easier if the marbles, rocks & legos were simply put into separate containers. By creating a new table for new forms, Sitefinity is creating this new container. This makes it easier (and FASTER!) for Sitefinity to retrieve this information.
Um, aren’t databases extremely good at filtering?
My analogy is going to look dumb to any DBA. However, I’m simplifying to illustrate the concept.
In reality, a well defined database schema can easily deal with the example I above. Databases are very good at eliminating data from a result set. Consequently, although the task above would be hard for humans, it’s easy for a database to quickly filter well defined items.
However, Sitefinity has another challenge. In the example above, each item had 2 attributes (size & color). Sitefinity needs to deal with an unlimited number of types and attributes. The attributes used to describe a person, would be very different than the attributes used to describe a car. We have no way of knowing (at design-time) what attributes you will invent for your web site. The form you’re building in Sitefinity could represent anything.
Consequently, a static database schema would need to be ultra generic (XML or objects that map to an arbitrary list of key/value pairs) to describe this unknown object. This type of generic schema requires the database to do a lot of work to query the data. This results in very poor performance. To compensate for this challenge many CMS’s require heavily on caching.
Sitefinity is circumventing these limitations by created dedicated tables for new objects.
How is this being done?
To make this happen, Sitefinity is utilizing a powerful set of features found in Telerik’s OpenAccess ORM.
- Artificial Fields
- Schema Change API
These new features allow Sitefinity to make database schema changes at runtime. Within Sitefinity, we’re calling this functionality Dynamic Data. Furthermore, there is a whole set of Fluent API’s that can be used to interact with these dynamic data objects in very rich ways.
But what about…?
This is just the tip of the iceberg. For example, what happens when form elements get removed and the database schema needs to change? What happens when a form is removed? Is data lost? How can these objects be accessed using the API? How can the database column names be modified?
We’ll explore these questions in future blog posts.