基于公司而不是用户的复杂领域模型

发布于 2024-11-25 10:56:00 字数 972 浏览 2 评论 0原文

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

不同类型的公司:

客户 供应商 每个代理

在数据库中都有自己的表,链接到主表公司,该表存储所有常见数据,例如地址、电话、电子邮件、公司类型以及相关表的 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. 供应商用户想要访问:AllCompanies, - 显示所有公司的列表
  2. 然后供应商公司的用户想要查看特定公司详细信息,现在如果是客户,我需要显示 ClientDTO 还是SupplierDTO?在本例中,我想向特定公司展示完整详细信息

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

例如 GetCompanyByID(int companyid);GetClientByID(int clientid); 我应该在这两个实例中返回什么类型的对象,假设我想在这两个实例中获得客户详细信息...

I have a few different types of companies that can access my web application e.g

Different types of Companies:

Client
Supplier
Agent

Each have their own table in the database, linked to the main table Company which stores all common data e.g. Address, Tel, Email, TypeOfCompany with a FK to the relevant table (Client etc.)...

What is the best way to handle this OO throughout my app?

I currently do something like:

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...
}

then inherit from that class and add aditional properties e.g.

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

However I am finding it problematic at times for example

  1. Supplier user wants to access: AllCompanies, - show a list of all companies
  2. Then the user from the Supplier Company wants to view a specific companies detail, now if it is a client I will need to show ClientDTO or SupplierDTO? In this instance I want to show that specific companies Full details

What would be the best way to handle this?

e.g. GetCompanyByID(int companyid); or GetClientByID(int clientid); What type of object should I return in both instances, presuming I want Client details in both instances...

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

寄居人 2024-12-02 10:56:00

有趣的是,数据库不理解诸如派生、聚合和封装之类的面向对象实践。这是一个不幸的失败,但仍然只是总体上称为“数据库阻抗不匹配”。

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

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

  1. 像您所做的那样拆分表格。
  2. 在同一个表中声明所有派生类型的所有字段。
  3. 使用 blob 字段(json/xml/其他)来容纳不常见的字段。

其次是你提出的问题,从数据库请求数据。主要是围绕“公共”基本类型列表的请求以及如何访问它们不共享的不常见字段。同样有几种可能性。

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

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

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

Funny how databases don't understand OO practices like derivation, aggregation, and encapsulation. It is an unfortunate failing but still only a part of what is overall referred to as "database impedance mismatch".

What your attempting to do is common enough there are several solutions...

Firstly there is the choice of the data model stored. There are basically three possibilities.

  1. Split the tables as you have done.
  2. Declare all fields for all derived types in the same table.
  3. Use a blob field (json/xml/whatever) to house the uncommon fields.

Secondly there is the issue you bring up, requesting the data from the database. Primarily this is centered around the request of a list of the 'common' base type and how to then access the uncommon fields that they don't share. Again there are several possibilities.

  1. When listing the base type only those common fields are returned. Then subsequent queries are issued one-off to lazy load the other fields.
  2. When listing the base type all other tables needed are also outer joined to the main table to ensure all fields are available to instantiate the object model fully.
  3. When listing the base type, multiple result sets are returned, one for each 'sub type' table that may be needed for the results. The client then pieces the records together building up the object model until it is complete.

Not an exhaustive list, but a start. Personally I prefer to avoid data models like the one you describe for this reason. Essentially my preference is to have the data model define the union of all fields (model #2), and then use a business layer to determine what properties are exposed, validated, required, etc. I have also used model #3 above, using blob fields for multiple values, and it works well enough also depending upon need. The only downside to model #3 over #2 is that you will not be able to query or sort on those fields. Ultimately either approach still needs the business logic layer involved to know what data to expose.

Remember databases are stupid, treat them as such and you will get along well. (note: this advice does not work on people, just databases)

裂开嘴轻声笑有多痛 2024-12-02 10:56:00

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

当您需要公司列表时,您不是在询问 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. 单击“添加”

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

I want to access: AllCompanies, - show a list of all companies

When you want a list of companies, aren't you asking for the general details that instances of CompanyDTO describe? Maybe your data access (service, repository, etc) could look like:

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

Then you asked (well, there is a question mark)

Then I want to view a specific companies detail, now if it is a client I will need to show ClientDTO or SupplierDTO?

I'm assuming this would be a separate view, or at least broken down into a separate partial views. But, you could use Display Templates to describe your child types of companies since you've describes an inheritance above.

I will pretend you showed us your controller and it looks like this:

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

Then, add a strongly-typed view named Details, that inherits a CompanyDTO object, and add a call to Html.DisplayForModel():

<%--some scaffolded code ommitted for brevity--%>

<asp:Content ID="Content2" ContentPlaceHolderID="MainContent" runat="server">

    <%= Html.DisplayForModel() %>

</asp:Content>

Then, here's where display templates come in. Add a folder:

~/Views/Company/DisplayTemplates

Then add to that folder 3 strongly-typed, partial views--one for each child type. Visual Studio will help you with this:

  1. Right-click the DisplayTemplates folder --> Add View...
  2. Name it "ClientDTO" (this is important)
  3. tick "Create a partial view"
  4. tick "Create a strongly-typed view"
  5. Select the ClientDTO class
  6. Select Details for view content (this will give you some auto generated markup)
  7. Click Add

Repeat this process for other child types and the correct template will be rendered based on the child type of the model passed to your Details view.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文