由于我所工作的网站的设计方式的特性,我现在必须解决一个问题。
我会尝试以无语言依赖的方式写出这个问题,但是该网站是用ASP.Net和C#完成的。
我们网站的结构如下所示: 对于任何给定的“对象”,它的结构如下:
ASPX页面 多个用户控件(ascx页面) 文本框、组合框、标签、按钮等
这意味着,如果我们有一个用户页面,那么该页面可能有3个用户控件。一个用于用户信息(姓名,电子邮件等),一个用于地址(城市,州,邮政编码等),一个用于区域设置(时区,语言等)。
这3个用户控件中的所有字段都存储在数据库的同一张表中。
现在,我们正在使用DataBinding和EntityFrameworks来填充数据,这意味着当我们保存一个对象时,我们实际上是调用save 3次(每个UserControl一次)。
因为UserControl只知道它包含的字段,所以当Databinding保存时,“它认为”其他字段现在为空(即Address控件保存后,“Email”和“Name”现在是空值)。为了“修复”这个问题,有一种方法叫做“MapOldToNew”,它会去获取旧记录并在即将保存的新对象上填充值。这是通用的,这意味着我们没有一个在Address Usercontrol上的方法,说“去获取Name和Email字段并填充它们”,而是遍历实体(对象)的所有属性,如果新对象上的值为NULL但旧对象(即将被覆盖的当前数据库中的那个对象)上的值不为NULL,它将使新值等于旧值。
问题是日期。我们允许在数据库中使用NULL日期。
如果用户填写了“生日”并保存,他们现在在数据库中的该字段中有一个生日值。 如果他们回到网页并清除生日字段并保存,MapOldToNew方法会获取旧记录,看到生日在旧记录中不为null,在即将保存的新对象上为null,它将用旧值(例如'7/23/1981')覆盖新值(NULL)。
解决方案?
我们网站的结构如下所示: 对于任何给定的“对象”,它的结构如下:
ASPX页面 多个用户控件(ascx页面) 文本框、组合框、标签、按钮等
这意味着,如果我们有一个用户页面,那么该页面可能有3个用户控件。一个用于用户信息(姓名,电子邮件等),一个用于地址(城市,州,邮政编码等),一个用于区域设置(时区,语言等)。
这3个用户控件中的所有字段都存储在数据库的同一张表中。
现在,我们正在使用DataBinding和EntityFrameworks来填充数据,这意味着当我们保存一个对象时,我们实际上是调用save 3次(每个UserControl一次)。
因为UserControl只知道它包含的字段,所以当Databinding保存时,“它认为”其他字段现在为空(即Address控件保存后,“Email”和“Name”现在是空值)。为了“修复”这个问题,有一种方法叫做“MapOldToNew”,它会去获取旧记录并在即将保存的新对象上填充值。这是通用的,这意味着我们没有一个在Address Usercontrol上的方法,说“去获取Name和Email字段并填充它们”,而是遍历实体(对象)的所有属性,如果新对象上的值为NULL但旧对象(即将被覆盖的当前数据库中的那个对象)上的值不为NULL,它将使新值等于旧值。
问题是日期。我们允许在数据库中使用NULL日期。
如果用户填写了“生日”并保存,他们现在在数据库中的该字段中有一个生日值。 如果他们回到网页并清除生日字段并保存,MapOldToNew方法会获取旧记录,看到生日在旧记录中不为null,在即将保存的新对象上为null,它将用旧值(例如'7/23/1981')覆盖新值(NULL)。
解决方案?
- 重新设计我们的系统,不使用UserControls,而是将所有控件放在同一页上,从而减少保存次数并且不需要MapOldToNew。现在,让我们假设这是一个不可能的解决方案(即使出于很多原因我觉得应该这样做)。
- 将所有日期存储为字符串,并在加载和保存时进行转换。(字符串没有同样的问题,因为一旦字符串被修改,它现在是一个空字符串,而不是NULL)
- 不允许数据库中有NULL日期,始终存储DateTime.MinValue并且不要在加载时显示它。
这些是我头脑中想到的想法。为了论证,让我们假设#1不可能(因为我感觉管理层不会喜欢它需要花费的时间)。
你会如何“修复”这个问题?
另一个解释
这里是更详细地分解问题。用户记录有两个字段。名称和出生日期。
假设有一个带有两个UserControls(ascx)的ASPX页面。
UserControl1有一个单独的DatePicker DataBound到“BirthDate”。
UserControl2有一个单独的TextBox DataBound到“Name”。
当UserControl1对ObjectContext调用Update时,它发送的User对象如下:
{ Name = NULL, BirthDate = 8/13/1980 }
MapOldToNew查看数据库记录并发现Name应该是"Bob",因此填充该值并保存记录。
UserControl2现在调用更新,用户对象如下:
{ Name = "John", BirthDate = NULL }
MapOldToNew发现BirthDate为NULL,因此它会从数据库中覆盖它并保存记录,数据库中的值是正确的。
现在假设用户回去并删除了BirthDate的值。当UserControl2调用MapOldToNew时,它会看到BirthDate为NULL(用户想要这样),并从数据库中覆盖它。
如果它没有从数据库中覆盖它,它将始终将其保存为空,并且用户将无法设置BirthDate。
MapOldToNew
函数。我不熟悉 Entity-Framework,但应该可以从数据库中加载旧值,覆盖 UC 中的列并保存它。如果能够部分更新记录(仅更改的列),那就更好了,这是可能的吗? - Tim Schmelter