【问题标题】:Business/Domain Object in ASP.NETASP.NET 中的业务/域对象
【发布时间】:2010-10-21 03:23:17
【问题描述】:

只是试图收集有关通过 ASP.NET (2.0+) UI/Presentation 层操作业务/域对象的有效/无效的想法。特别是在 ASP.NET 代码直接与业务层对话的经典 ASP.NET LOB 应用程序情况下。我经常遇到这种类型的设计,想知道什么是理想的解决方案(即实现特定的模式),以及在没有实现“模式”的情况下不需要完全重写的最佳实用解决方案是什么。

这是一个示例场景。

作为特定业务/域对象的“编辑/新建”页面的单个 ASP.NET 页面,让我们以“人员”为例。我们想在此页面中编辑姓名和地址信息。当用户进行编辑或输入数据时,在某些情况下表单应该回发以刷新自身。例如,在编辑地址时,他们选择“国家”。之后,州/地区下拉菜单将启用并刷新所选国家/地区的相关信息。这本质上是业务逻辑(根据某些依赖字段限制可用选择),并且此逻辑由业务层处理(请记住,这只是一个示例,在许多业务情况下,回发期间逻辑更复杂 - 对于例如,保险行业在选择某些事物时决定需要/需要哪些其他数据。

理想情况下,此逻辑仅存储在业务/域对象中(即在 ASP.NET 代码中没有重复的逻辑)。为此,我认为 Business/Domain 对象需要重新初始化,并根据每次回发时的当前 UI 值设置其状态。

例如:

private Person person = null;

protected void Page_Load()
{
    person = PersonRepository.Load(Request.QueryString["id"]);

    if (Page.IsPostBack)
        SetPersonStateFromUI(person);
    else
        SetUIStateFromPerson(person);
}

protected void CountryDropDownList_OnChange()
{
    this.StateRegionDropDownList.Enabled = true;
    this.StateRegionDropDownList.Items.Clear();
    this.StateRegionDropDownList.DataSource = person.AvailableStateRegions;
    this.StateRegionDropDownList.DataBind();
}

我见过的其他选项是将业务对象存储在 SessionState 中,而不是在每次页面加载备份时从存储库(也称为数据库)加载它。

想法?

【问题讨论】:

    标签: asp.net design-patterns architecture domain-driven-design business-objects


    【解决方案1】:

    这句话我有点不同意:

    this.StateRegionDropDownList.DataSource = person.AvailableStateRegions;
    

    Person 是一个业务/域对象,但它不是应该处理状态/区域映射的对象(例如),即使这是做出决策的信息所在的位置。

    在需要多个变量来做出决定的更复杂的示例中,您通常想要做的是从您尝试结束的域对象开始,并在该对象上调用一个可以给定的函数做出业务决策所需的所有信息。

    所以也许(在 State 类上使用静态函数):

    this.StateRegionDropDownList.DataSource = State.GetAvailableStateRegions(person, ipAddress);
    

    由于将 UI 助手关注点从 Person 域对象中分离出来,这种编程风格往往“更易于测试”。

    【讨论】:

    • 我也有点偏离我原来的想法。我一直在阅读 MVVM 设计模式,似乎这个逻辑真的应该在视图模型中。这实质上有助于促进数据进入业务层(地址对象)。
    【解决方案2】:

    对于非常简单的事情,我不会使用常规回发,而是会使用 ajax 方法。例如,如果我需要获取城市列表,我可能有一个页面方法(或 Web 服务),它给定一个状态给我一个城市列表。

    如果您的选择取决于多种参数,那么您的做法会很有效。至于在 Session 中存储东西是有好处的。您的实体是否同时对多个可见?如果是这样,当用户 A 和用户 B 都编辑相同内容时会发生什么。另外,如果您每次加载都是每次都保存到数据库中吗?如果我正在编辑我的名字,然后选择国家,但现在我的浏览器崩溃了,会发生什么情况。您是否更新了数据库中的名称?

    【讨论】:

    • 并发通常通过 DAL 处理并冒泡。也就是说,如果用户 A 和用户 B 正在编辑同一个“人”,则首先赢得保存操作。第二个会显示一条错误消息并显示业务对象的最新副本。
    • 在用户采取明确的保存操作之前不保存到数据库(想想“保存”按钮)。每次加载时仅从数据库加载当前状态。 ....Ahhhh 现在我明白了您对并发性的要求...如果用户 A 和用户 B 同时编辑,用户 A 保存,并且用户 B 执行导致回发的操作,我从存储库中的负载将加载用户 A 的编辑...必须以某种方式使用并发 ID 跟踪对象的当前版本。
    • 是的,这就是我所说的。
    【解决方案3】:

    我会将您的示例放在我的“UI 增强”存储桶而不是 BL 中,验证条目是否正确是 BL,但在我看来,缓动数据输入是 UI。

    【讨论】:

    • 那将是重复逻辑,你不觉得吗?也就是说,如果我选择一个国家,给定该对象状态,我的地址对象知道所选国家/地区的可用州/地区是什么。也许使用 Country/Regions 我们可以摆脱它,但是更复杂的事情呢?比如根据另一个字段的选择需要哪些字段。
    • 并非如此,逻辑只会存在于 UI 层。虽然您可能会验证 BL 层中的输入(假设您的 UI 有一个接口,这意味着它们不是同一个单体应用程序的一部分)但您不会在业务对象中实现状态/区域级联,它只是不适合。对我来说,BL 层所做的事情可以通过机器生成或用户输入来调用,它不依赖于用户界面。我承认这是一种观点,我可能是错的 :)
    猜你喜欢
    • 2012-05-27
    • 1970-01-01
    • 2014-02-24
    • 1970-01-01
    • 2011-08-01
    • 2010-10-18
    • 1970-01-01
    • 2016-12-06
    相关资源
    最近更新 更多