基于消息的服务应如何处理检索操作?

时间:2014-05-13 08:34:02

标签: servicestack soa

我一直在寻找基于消息的服务(ServiceStack风格)并远离WCF风格的服务(几乎是RPC)。从使用WCF风格的服务,我看到一些缺点,我想尝试另一种方法。它让我觉得WCF方法不能真正有重载,我理解为什么,我知道有很多方法可以解决它,但那些让我觉得很烦。基于消息的服务承认事情已经过时。

我遇到的问题是如何处理检索数据。 ServiceStack(和其他API)似乎有一个请求对象,用于获取单个实体或实体集合。此请求对象具有许多可选参数。例如

public GetInvoiceRequest
{
    public int? InvoiceId {get; set;}

    public int? AccountId {get; set;}

    public DateTime? From {get; set;}
}

public GetInvoiceResponse
{
    public List<InvoiceDto> {get;set;}

    public ResponseStatus Status {get;set;}
}

此类事物的标准做法是什么?您是否包含每个可选参数的发票?因此,您获得了ID的发票,然后如果还设置了AccountId,则添加该帐户的所有发票,如果还设置了From,则添加特定日期的所有发票?有效地执行工会。或者你执行这些集合的交集?或者您只是尊重设置的第一个参数。因此,如果设置了所有参数,则只返回与InvoiceId匹配的Invoice,因为这是遇到的第一个参数?

2 个答案:

答案 0 :(得分:3)

您有正确的想法,并且您的方法是有效的,但人们倾向于将请求特定发票的意图与发票清单请求分开。

我倾向于建立一种服务,使我的DTO遵循C-R-U-D-L操作格式,即。创建读取更新删除列表键入DTO:

所以当我有一个ReadInvoiceRequest 而不是GetInvoiceRequest 时,我知道将始终返回一个InvoiceDto对象,并且需要InvoiceId参数:

[Route("/invoices/{InvoiceId}", "GET")]
[Route("/account/{AccountId}/invoices/{InvoiceId}","GET")]
public ReadInvoiceRequest : IReturn<InvoiceDto>
{
    public int InvoiceId { get; set; } // InvoiceId is always expected
    public int? AccountId { get; set; }
    public DateTime? From { get; set; }
}

专门用于列表的路线将始终返回InvoiceDto

的列表
[Route("/invoices", "GET")]
[Route("/account/{AccountId}/invoices","GET")]
public ListInvoicesRequest : IReturn<List<InvoiceDto>>
{
    public int? AccountId { get; set; }
    public DateTime? From { get; set; }
}

如果指定了InvoiceId并且您的返回类型是结果列表,则可以防止返回多少结果的模糊性。

这也使消费者明白请求DTO中的可选参数将被视为过滤器。

您服务中的操作方法将与此类似:

public class MyInvoiceService : Service
{
    // CREATE
    public int Post(CreateInvoiceRequest request)
    {
        // Return the InvoiceId of the created record
    }

    // READ
    public InvoiceDto Get(ReadInvoiceRequest request)
    {
        var invoice = ... // request.InvoiceId; (filter by AccountId & From if set)
        return invoice;
    }

    // UPDATE
    public void Post(UpdateInvoiceRequest request)
    {
        // Handle update
        // I don't return anything, only throw exceptions if update fails
        // Success is indicated by 200 status
    }

    // DELETE
    public void Delete(DeleteInvoiceRequest request)
    {
        // Handle delete
        // I don't return anything, only throw exceptions if delete fails
        // Success is indicated by 200 status
    }

    // LIST
    public List<InvoiceDto> Get(ListInvoicesRequest request)
    {
        var invoices = ... // (filter by AccountId & From if set)
        return invoices;
    }
}

从服务消费者的角度来看,我认为从分离的DTO中获得的回应不确定性较低。

答案 1 :(得分:1)

ServiceStack API已从一个Request和匹配的Response DTO模式转移。 ServiceStack现在允许许多不同的请求DTO以及明确指定响应对象的能力。

你应该看到这个答案:ServiceStack Request DTO design

但通常在执行搜索时我会使用可选(可空)属性并动态生成搜索查询。