【问题标题】:ASP.NET Site architecture issueASP.NET 站点架构问题
【发布时间】:2011-09-13 03:35:53
【问题描述】:

由于我正在开发的网站的设计方式的性质,我现在必须解决一个问题。
我将尝试将此问题编写为与语言无关,但该站点是在 ASP.Net 中使用 C# 完成的。

概述

对于任何给定的“对象”,我们网站的结构如下所示:

  • ASPX 页面
    • 多个用户控件(ascx 页面)
      • 文本框、组合框、标签、 按钮等

这意味着,如果我们有一个用户页面并且该页面可能有 3 个用户控件。一个用于用户信息(姓名、电子邮件等),一个用于地址(城市、州、邮编等),一个用于区域设置(时区、语言等)

3 个用户控件上的所有这些字段都存储在数据库的同一个表中。

现在,我们使用 DataBinding 和 EntityFrameworks 来填充数据,这意味着当我们保存一个对象时,我们实际上调用了 3 次 save(每个 UserControl 1 次)。

(与语言无关:我们实际上并没有 分配像User.Name = "Bob" 这样的值,它由框架处理)

因为 UserControl 只知道它包含的字段,所以当数据绑定保存它“认为”其他字段现在是空白的。 (即地址控制保存,现在“电子邮件”和“名称”为空值)。为了“解决”这个问题,有一个名为“MapOldToNew”的方法,它会抓取旧记录并填充即将保存的新对象上的值。这是通用的,这意味着我们在 Address Usercontrol 上没有一个方法说“去获取 Name 和 Email 字段并填写它们”,而是循环遍历 Entity(object) 的所有属性以及如果一个值在新对象上是NULL,但在旧对象上是NOT NULL(当前在数据库中即将被覆盖的对象),它将使新值等于旧值。

问题

日期。我们允许在我们的数据库中使用 NULL 日期。

如果用户填写“生日”并保存,他们现在在数据库中的字段中有一个生日值。
如果他们返回并清除网页上的“生日”字段并保存,MapOldToNew 方法会抓取旧记录,看到“生日”不为空,并且在要保存的新对象上为空,它将覆盖新值 (NULL) 与旧值(例如 '7/23/1981')。

解决方案?

  1. 返工我们的系统以不使用 UserControls 而是拥有所有 控制同一页,从而 减少我们需要的次数 保存而不需要 MapOldToNew。现在,让我们 假设这是不可能的 解决方案(即使它是一个 我觉得应该为 很多原因)。
  2. 全部存储 日期作为字符串并进行转换 在加载和保存。 (字符串不 有同样的问题,因为一旦 字符串已修改,现在是 一个空字符串,而不是 NULL)
  3. 不允许在 数据库并始终存储 DateTime.MinValue 并且不要 加载时显示。

这些是我脑海中浮现的想法。为了争论起见,让我们假设#1是不可能的(因为我觉得管理层不会喜欢完成所需的时间)。

你会如何“解决”这个问题?

另一种解释

这里有更多的问题。 用户记录有 2 个字段。姓名和生日。
假设有 1 个带有 2 个用户控件 (ascx) 的 ASPX 页面。
UserControl1 有一个 DatePicker 数据绑定到“BirthDate”。
UserControl2 有一个文本框数据绑定到“名称”。
当 UserControl1 在 ObjectContext 上调用 Update 时,它​​发送的 User 对象如下所示:

{ Name = NULL, BirthDate = 8/13/1980 }  

MapOldToNew 查看数据库记录,发现名称应该是“Bob”,因此它会填充值并保存记录。

UserControl2 现在调用 Update,User 对象如下所示:

{ Name = "John", BirthDate = NULL }

MapOldToNew 发现 BirthDate 为 NULL,因此它使用数据库中的 8/13/1980 覆盖它,并且记录保存并且数据库具有正确的值。

现在假设用户返回并删除 BirthDate 值。当 UserControl2 调用 MapOldToNew 时,它发现 BirthDate 为 NULL(用户想要的)并从数据库中覆盖它。
如果它没有从数据库中覆盖它,它将始终将其保存为 NULL,并且用户将永远无法设置 BirthDate。

【问题讨论】:

  • 当然问题与语言无关。否则,如果您在 VB.NET 中编程,您可能不会遇到完全相同的问题。
  • 是的,但它也与 ASP.Net 无关。从 MVC 模式的角度来看它。一个视图有多个子视图,它们都使用部分填充的模型调用同一个 Controller.Save,因此它们都调用 MapOldToNew,它用数据库中的值覆盖 NULL 日期。
  • 你的问题是MapOldToNew-function。我不熟悉 Entity-Framework,但必须可以从数据库中加载旧值,覆盖 UC 中的列并保存它。如果可以(不是吗?)部分更新记录(仅更改的列),那就更好了。
  • 谷歌搜索几分钟后,我找到了Stub Entities。看看这个视频:screencast.com/t/ZGQyY2I5ZWE
  • @Tim - 这可能值得一看,但需要在 100 多个用户控件上手动填充大约 50 多个实体

标签: asp.net language-agnostic architecture


【解决方案1】:

我会重构 MapOldToNew 以理解可为空的类型。我假设您有一个可以为空的日期(例如 datetime?或 Nullable,如果是这样 - 不要假设如果为 null 则覆盖。

由于类型到模型的映射,未来考虑 MVC 或 WebForms 考虑动态数据。 http://aspnet.codeplex.com/wikipage?title=Dynamic%20Data

【讨论】:

  • 是的,但是在这种情况下你将如何重构 MapOldToNew?如果更新实体上的 Date 为 NULL,我们如何知道它是 NULL 是因为用户将其置空,还是因为它不在调用 Update 的 UserControl 中而为 NULL?
  • 如果您总是进行所有三个更新,那么您肯定不想全部保存三次。您需要将其合并到一个模型中,该模型在保存之前映射每个用户控件的值,或者创建一个新的复合控件来处理它。如果您不想将其重构为保存一次,那么您只需要更新那部分信息 - 而无需关心其余部分。 IE 你的更新过程只需要知道地址是否为空,更新为空。如果地址不为空,请分配一个值 - 并且不要触及任何其他字段。三个更新虽然我肯定会考虑重构
  • 我完全同意你的重构。问题是我的例子不是现实生活中的情况,只是一个简化的解释。实际上,可能有 50 多个具有数百个用户控件的实体需要重构。我正在寻找的是一种无需重构的方法。我很确定这是不可能的,但我希望比我更聪明的头脑能想出办法。
  • 但是如果你们都经历过这个通用方法,那么只需重构那个方法。如果此 OldToNew 方法假定它将保留原始值 - 那么您需要在该方法中更改该行为 - 如果不重构其他所有内容,则没有其他方法。您的优势在于您通过一种通用方法 - 没有看到整个系统,只有一个简化的案例,这就是我认为的方式,所以 - 您可以更改 MapOldToNew 以更改此空行为吗?您能否发布一个示例说明为什么这会失败 - 例如因为实体行为?
  • 在上面发布不同的解释。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-08-02
  • 1970-01-01
  • 2011-03-29
  • 2011-03-03
  • 2011-03-29
  • 1970-01-01
相关资源
最近更新 更多