基于公司而非用户的复杂域模型

本文关键字:用户 复杂 模型 于公司 公司 | 更新日期: 2023-09-27 18:02:50

我有几种不同类型的公司可以访问我的Web应用程序,例如

不同类型的公司:

客户供应商代理

每个在数据库中都有自己的表,链接到主表公司,该表存储所有常见数据,例如地址,电话,电子邮件,类型公司与FK到相关表(客户等(...

在整个应用中处理此 OO 的最佳方式是什么?

我目前做这样的事情:

public class CompanyDTO
{
  public int Id {get;set;}
  public string Name {get;set;}
  public Address Address {get;set;}
  public string Type {get;set;} //type of company
  //etc...
}

然后从该类继承并添加附加属性,例如

public class ClientDTO : CompanyDTO
{
 public string Key {get;set;}
 public Address Billing {get;set;}
}

但是,例如,我有时发现它有问题

  1. 供应商用户想要访问: 所有公司, - 显示所有公司的列表
  2. 然后供应商公司
  3. 的用户想要查看特定公司的详细信息,现在如果是客户,我需要显示 ClientDTO 或 SupplierDTO?在这种情况下,我想向特定公司展示 全部详细信息

处理这个问题的最佳方法是什么?

例如 GetCompanyByID(int companyid);GetClientByID(int clientid); 在这两种情况下,我应该返回哪种类型的对象,假设我想要两个实例中的客户端详细信息......

基于公司而非用户的复杂域模型

有趣的是,

数据库不理解派生、聚合和封装等面向对象实践。 这是一个不幸的失败,但仍然只是总体上称为"数据库阻抗不匹配"的一部分。

您尝试做的事情很常见,有几种解决方案......

首先是存储的数据模型的选择。 基本上有三种可能性。

  1. 像以前一样拆分表。
  2. 在同一表中声明所有派生类型的所有字段。
  3. 使用 blob 字段(json/xml/whatever(来容纳不常见的字段。

其次,您提出的问题是,从数据库中请求数据。 这主要集中在"通用"基本类型列表的请求以及如何访问它们不共享的不常见字段。 同样有几种可能性。

  1. 列出基类型时,仅返回那些公共字段。 然后一次性发出后续查询以延迟加载其他字段。
  2. 列出基类型时,所需的所有其他表也都外部联接到主表,以确保所有字段都可用于完全实例化对象模型。
  3. 列出基类型时,将返回多个结果集,结果可能需要的每个"子类型"表对应一个结果集。 然后,客户端将这些记录拼凑在一起,构建对象模型,直到它完成。

不是详尽的清单,而是一个开始。 就个人而言,出于这个原因,我更喜欢避免使用您描述的数据模型。 从本质上讲,我的偏好是让数据模型定义所有字段的联合(模型 #2(,然后使用业务层来确定公开、验证、必需等属性。 我还使用了上面的模型 #3,将 blob 字段用于多个值,并且根据需要也运行良好。 模型 #3 优于 #2 的唯一缺点是您将无法对这些字段进行查询或排序。 最终,这两种方法仍然需要所涉及的业务逻辑层来了解要公开哪些数据。

记住数据库是愚蠢的,这样对待它们,你会相处得很好。 (注意:此建议不适用于人,仅适用于数据库(

我想访问: 所有公司, - 显示所有公司的列表

当您想要公司列表时,您不是在询问CompanyDTO实例描述的一般细节吗?也许您的数据访问(服务、存储库等(可能如下所示:

public class CompanyRepository : ICompanyRepository
{
    public IEnumerable<CompanyDTO> GetCompanies()
    {
        // get companies and map them to CompanyDTO objects as necessary
    }
}

然后你问(嗯,有一个问号(

然后我想查看特定的公司详细信息,现在如果是客户,我需要显示 ClientDTO 还是 SupplierDTO?

我假设这将是一个单独的视图,或者至少分解为一个单独的部分视图。但是,您可以使用显示模板来描述子类型的公司,因为您已经在上面描述了继承。

我会假装你向我们展示了你的控制器,它看起来像这样:

public class CompanyController : Controller
{
    public ActionResult Details(int id)
    {
        CompanyRepository repo = new CompanyRepository();
        return View(repo.GetCompanyById(id));
    }
}

然后,添加一个名为 Details 的强类型视图,该视图继承CompanyDTO对象,并添加对 Html.DisplayForModel() 的调用:

<%--some scaffolded code ommitted for brevity--%>
<asp:Content ID="Content2" ContentPlaceHolderID="MainContent" runat="server">
    <%= Html.DisplayForModel() %>
</asp:Content>

然后,这就是显示模板的用武之地。添加文件夹

~/Views/Company/DisplayTemplates

然后将 3 个强类型视图添加到该文件夹 - 每个子类型一个。Visual Studio将帮助您:

  1. 右键单击DisplayTemplates文件夹 -->添加视图...
  2. 将其命名为"ClientDTO"(这很重要(
  3. 勾选"创建部分视图">
  4. 勾选"创建强类型视图">
  5. 选择ClientDTO
  6. 选择Details查看内容(这将为您提供一些自动生成的标记(
  7. 点击添加

对其他子类型重复此过程,将根据传递到详细信息视图的模型的类型呈现正确的模板。