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

时间:2011-07-20 20:22:25

标签: c# design-patterns domain-driven-design domain-model

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

不同类型的公司:

客户端 供应商 剂

每个数据库中都有自己的表,链接到主表公司,该表存储所有常见数据,例如地址,电话,电子邮件,TypeOfCompany与相关表格的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...
}

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

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

然而,我发现它有时会出现问题

  1. 供应商用户想要访问:AllCompanies, - 显示所有公司的列表
  2. 然后来自供应商公司的用户想要查看特定公司详细信息,现在如果它是客户我将需要显示ClientDTO或SupplierDTO?在这种情况下,我想展示特定公司完整详细信息
  3. 处理此问题的最佳方法是什么?

    e.g。 GetCompanyByID(int companyid);GetClientByID(int clientid);我应该在两个实例中返回什么类型的对象,假设我在两个实例中都需要客户端详细信息...

2 个答案:

答案 0 :(得分:3)

有趣的是,数据库如何理解OO实践,如派生,聚合和封装。这是一个不幸的失败,但仍然只是整体被称为“database impedance mismatch”的一部分。

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

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

  1. 按照您的方式拆分表格。
  2. 在同一个表中声明所有派生类型的所有字段。
  3. 使用blob字段(json / xml / whatever)来容纳不常见的字段。
  4. 其次,您提出了从数据库中请求数据的问题。主要是围绕“公共”基类型列表的请求以及如何访问它们不共享的不常见字段。还有几种可能性。

    1. 列出基本类型时,仅返回这些公共字段。然后一次性发出后续查询以延迟加载其他字段。
    2. 列出基本类型时,所有其他所需的表也外部连接到主表,以确保所有字段都可用于完全实例化对象模型。
    3. 列出基本类型时,会返回多个结果集,每个“子类型”表对应一个结果集。然后,客户端将记录分块,构建对象模型,直到完成为止。
    4. 不是一个详尽的清单,而是一个开始。就个人而言,我更愿意避免使用您为此描述的数据模型。基本上我的偏好是让数据模型定义所有字段的联合(模型#2),然后使用业务层来确定哪些属性被公开,验证,需要等等。我也使用了上面的模型#3,使用blob字段用于多个值,并且根据需要也可以很好地工作。模型#3优于#2的唯一缺点是您将无法查询或排序这些字段。最终,任何一种方法仍然需要涉及的业务逻辑层来了解要公开的数据。

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

答案 1 :(得分:1)

  

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

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

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

然后你问(好吧,有一个问号)

  

然后我想查看具体的公司细节,现在如果是客户我需要展示ClientDTO或SupplierDTO?

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

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

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文件夹 - &gt;添加视图...
  2. 将其命名为“ClientDTO”(这很重要)
  3. 勾选“创建局部视图”
  4. 勾选“创建强类型视图”
  5. 选择ClientDTO班级
  6. 为视图内容选择Details(这将为您提供一些自动生成的标记)
  7. 点击添加
  8. 对其他子类型重复此过程,将根据传递给“详细信息”视图的模型的类型呈现正确的模板。