12

征求有关“最佳”模式的反馈/选项/评论,以用于我的服务中的参考数据。

参考数据是什么意思?

让我们以罗斯文为例。订单与数据库中的客户相关。当我实现我的订单服务时,在某些情况下,我希望引用来自订单的“完整”客户,而在其他情况下,我只想引用客户(例如键/值对)。

例如,如果我正在执行 GetAllOrders(),我不想返回一个完全填写的订单,我想返回一个订单的轻量级版本,每个订单的客户只有参考数据。但是,如果我执行 GetOrder() 方法,我可能想要填写客户详细信息,因为此方法的使用者可能需要它。在其他情况下,我可能想要求在某些方法调用期间填写客户详细信息,但留给其他人。

这是我想出的:

[DataContract]
public OrderDTO
{
    [DataMember(Required)]
    public CustomerDTO;

    //etc..
}

[DataContract]
public CustomerDTO
{
    [DataMember(Required)]
    public ReferenceInfo ReferenceInfo;

    [DataMember(Optional)]
    public CustomerInfo CustomerInfo;
}

[DataContract]
public ReferenceInfo
{
    [DataMember(Required)]
    public string Key;

    [DataMember(Required)]
    public string Value;
}

[DataContract]
public CustomerInfo 
{
    [DataMember(Required)]
    public string CustomerID;

    [DataMember(Required)]
    public string Name;

    //etc....
}

这里的想法是,由于在 CustomerDTO 中始终需要 ReferenceInfo(这是一个通用的键/值对),因此我将始终拥有 ReferenceInfo。它为我提供了足够的信息,以便稍后在需要时获取客户详细信息。让 CustomerDTO 需要 ReferenceInfo 的缺点是,当我获得完整的 CustomerDTO(即填写了 CustomerInfo)时,它可能有点过头了,但至少我可以保证参考信息。

是否有一些其他的模式或框架可以用来使这个场景/实现“更干净”?

我问的原因是,虽然我们可以简单地说在 Northwind 中总是返回一个完整的 CustomerDTO,但这在简单的 Northwind 情况下可能工作得很好。就我而言,我有一个具有 25-50 个字段的对象,这些字段是引用/查找类型的数据。在不同的情况下,有些比其他的加载更重要,但我希望这些引用类型的定义尽可能少(这样我就不会陷入“DTO 维护地狱”)。

意见?反馈?注释?

谢谢!

4

7 回答 7

2

亚马逊产品广告 API Web 服务就是您遇到的相同问题的一个很好的例子。

他们使用不同的 DTO 为调用者提供或多或少的详细信息,具体取决于他们的情况。例如有小反应组大反应组中反应组

如果您说您不想要一个健谈的界面,那么拥有不同的 DTO 是一种很好的技术。

于 2009-09-18T11:37:45.350 回答
2

我们在项目上处于相同的决策点。截至目前,我们决定创建三个级别的 DTO 来处理事物:SimpleThing、ComplexThing 和 FullThing。不过,我们不知道它会如何为我们工作,所以这还不是一个基于现实的答案。

我想知道的一件事是,我们是否可以了解到我们的服务是在“错误”级别设计的。例如,是否存在我们应该将 FullThing 拆开而只传递 SimpleThing 的实例?如果我们这样做,这是否意味着我们不恰当地将某些业务逻辑置于过高的级别?

于 2009-07-09T19:48:07.393 回答
1

我们在对象关系映射中也遇到过这个问题。在某些情况下,我们想要完整的对象,而在其他情况下,我们想要引用它。

困难在于,通过将序列化烘焙到类本身中,数据契约模式强化了这样一种观念,即只有一种正确的方法来序列化一个对象。但是在很多情况下,您可能希望部分序列化一个类和/或其子对象。

这通常意味着每个类必须有多个 DTO。例如,FullCustomerDTO 和 CustomerReferenceDTO。然后,您必须创建将不同 DTO 映射回客户域对象的方法。

可以想象,这是一项繁重的工作,其中大部分工作非常乏味。

于 2009-07-09T21:07:36.577 回答
1

我已经决定反对我将要采取的方法。我认为我最初的许多担忧是由于缺乏需求造成的。我有点预料会是这种情况,但很想知道其他人可能如何解决这个问题,即确定何时加载某些数据以及何时不加载。

我正在展平我的数据合同以包含最常用的参考数据元素字段。这应该适用于大多数消费者。如果提供的数据对于给定的消费者来说不够用,他们可以选择查询单独的服务以提取特定参考实体(例如货币、州等)的完整详细信息。对于实际上基本上是键/值对的简单查找,我们将使用通用键/值对数据协定来处理它们。我什至可以将 KnownType 属性用于我更专业的键/值对。

[DataContract]
public OrderDTO
{
    [DataMember(Required)]
    public CustomerDTO Customer;

    //in this case, I think consumers will need currency data, 
    //so I pass back a full currency item
    [DataMember(Required)]
    public Currency Currency; 

    //in this case, I think consumers are not likely to need full StateRegion data, 
    //so I pass back a "reference" to it
    //User's can call a separate service method to get full details if needed, or 
    [DataMember(Required)]
    public KeyValuePair ShipToStateRegion;

    //etc..
}


[DataContract]
[KnownType(Currency)]
public KeyValuePair
{
    [DataMember(Required)]
    public string Key;

    [DataMember(Required)]
    public string Value;

    //enum consisting of all possible reference types, 
    //such as "Currency", "StateRegion", "Country", etc.
    [DataMember(Required)]
    public ReferenceType ReferenceType; 
}


[DataContract]
public Currency : KeyValuePair
{
    [DataMember(Required)]
    public decimal ExchangeRate;

    [DataMember(Required)]
    public DateTime ExchangeRateAsOfDate;
}


[DataContract]
public CustomerDTO 
{
    [DataMember(Required)]
    public string CustomerID;

    [DataMember(Required)]
    public string Name;

    //etc....
}

想法?意见?注释?

于 2009-07-08T18:45:18.330 回答
1

对我来说,这似乎是一个复杂的解决方案。为什么不在 OrderDTO 类中有一个客户 ID 字段,然后让应用程序在运行时决定它是否需要客户数据。由于它具有客户 ID,因此它可以在决定时将数据拉下来。

于 2009-06-16T23:29:15.120 回答
1

另一种可能性是将对象视为财产包。在查询时指定您想要的属性,并准确返回您需要的属性。

更改属性以在“短”版本中显示然后不需要多次往返,您可以一次获取一组的所有属性(避免繁琐的界面),并且您不必修改数据或如果您决定“短”版本需要不同的属性,则操作合同。

于 2009-07-25T04:19:04.520 回答
1

我通常在复杂的 Web 服务(即发送/接收实体的 Web 服务)中构建延迟加载。如果一个人有一个父亲属性(也是一个人),我只发送一个父亲的标识符而不是嵌套对象,然后我只确保我的网络服务有一个可以接受一个标识符并用相应的人实体响应的操作. 然后,如果客户端想要使用父亲属性,它可以回调 Web 服务。

我还对此进行了扩展,以便可以进行批处理。如果一个操作发回 5 个 Person,那么如果在这些 Person 中的任何一个上访问了 Father 属性,那么将向所有 5 个 Father 及其标识符发出请求。这有助于减少 Web 服务的繁琐。

于 2009-09-22T19:47:08.533 回答