Due to the nature of the way the site I work on works, I have a problem that I must solve now.
I will try to write this question as language-independent, but the site runs in ASP.Net with C #.
Overview
The structure of our site looks like this for any given "object":
- Aspx page
- Multiple UserControls (ascx pages)
- Text fields, combobox, shortcuts, buttons, etc.
This means that if we have a user page, and this page can have 3 UserControls. One for user information (name, email address, etc.), One for address (city, state, zip code, etc.) And one for regional settings (time zone, language, etc.)
All these fields in 3 UserControls are stored in one table in the database.
Now we use DataBinding and EntityFrameworks to populate the data, which means that when we save the object, we actually call save 3 times (1 on the UserControl).
(Agnostic language: we actually do not assign values, such as User.Name = "Bob" , processed by the platform)
Because UserControl only knows about the fields it contains, when the Databinding keeps it “thinking”, the rest of the fields are now empty. (i.e., address management is retained, and now "Email" and "Name" are null values). To “fix”, there is a “MapOldToNew” method that exits and grabs the old record and populates the values of the new object that needs to be saved. This is general, which means that we don’t have a method in User User Control that says: “Go to the field“ Name and email address ”and fill them in,“ instead, it looks through all the properties of the Entity (object) object and if the value NULL for the new object, but NOT NULL for the old object (the one that is currently in the database that needs to be overwritten), it will make the New value equal to the old value.
Problem
Dates We give NULL dates in our database.
If the user fills in the "Birthday" and saves it, they now have the value "Birthday" in the field in the database.
If they return and clear the Birthday field on the web page and save, the MapOldToNew method grabs the old record, sees that the Birthday is not zero and Null on the new object that needs to be saved, it will override the New value (NULL) with old value (for example, "7/23/1981").
Solutions?
- Correct our system so as not to use UserControls, but instead all the controls on the same page, thereby reducing the number of times we need to save and not require
MapOldToNew . For now, let's assume that this is not a solution (although it is. I feel that there is a need to do this for many reasons). - Save all dates as strings and conversion by loading and saving. (Lines do not have the same problem since the line was changed, now an empty line, not NULL)
- Do not allow NULL dates in databases and always store
DateTime.MinValue and do not display it in load mode.
These are the ideas that I came up with from my head. For arguments, let's assume that # 1 is impossible (because I don't have control over the feeling for the time it takes to complete).
How would you “fix” this?
Another explanation
Here the problem is broken down more. User record has 2 fields. Name and date of birth.
Suppose there is 1 ASPX page with 2 UserControls (ascx).
UserControl1 has one DatePicker DataBound for "BirthDate".
User UserControl2 has one DataBound text field for "Name".
When UserControl1 calls Update on ObjectContext, the User object it sends is as follows:
{ Name = NULL, BirthDate = 8/13/1980 }
MapOldToNew looks at the database record and sees that the name should be "Bob", so it fills in the value and saves the record.
UserControl2 calls the update now, and the User object looks like this:
{ Name = "John", BirthDate = NULL }
MapOldToNew sees that BirthDate is NULL, so it overwrites it on 8/13/1980 from the database and saves the record, and the database has the correct values.
Now suppose the user returns and removes the value of BirthDate. When UserControl2 calls MapOldToNew, it sees that BirthDate is NULL (which the user wants) and overwrites it from the database.
If he did NOT overwrite it from the database, he would always save it as NULL, and the user could never set BirthDate.