【问题标题】:Sending queries from client to WCF service将查询从客户端发送到 WCF 服务
【发布时间】:2011-07-13 12:15:19
【问题描述】:

我想听听您对以下内容的看法。

我们将 SOA 视为解决我们遇到的一些概念问题的解决方案。我们不想多次构建相同的逻辑。所以想做一些WCF服务,让不同的客户端通过这些服务(甚至可能是Apple应用程序)检索数据。理想的情况是客户尽可能瘦,只关心演示。所有业务逻辑和数据访问都应在 WCF 服务中处理。

现在我的老板调查了这件事,他最担心的基本上是我们会陷入混乱。粗略地说,他设想我们将为要在数据库上执行的每个查询定义一个新方法。

比如:

  • RetrieveCustomerById
  • RetrieveCustomerByName
  • RetrieveCustomerByStoreId
  • RetrieveCustomerWithPersonalDetailsButWithoutAddressById
  • 等等……

所以他的想法是让客户端构建查询并将其发送到 WCF 服务。 WCF 服务执行查询、应用业务逻辑并返回结果。

我对你们能想出的所有缺点或优点都非常感兴趣。提前感谢您与我一起思考。

【问题讨论】:

    标签: .net wcf web-services architecture soa


    【解决方案1】:

    你的老板可能是对的,它或多或少是它的样子,但是

    • 首先,它必然有什么问题(尽管读到最后,因为其中一些没有意义)?
    • 不会有RetrieveCustomerWithPersonalDetailsButWithoutAddressById,因为CustomerWithPersonalDetailsButWithoutAddress 是不同的域模型。
    • 向业务逻辑传递查询非常让人想起以前在接口参数中定义为object(或者如果你和我一样老,在VB6 COM 中是Variant)。这意味着我们不想花精力去接受理解我们领域的挑战
    • RetrieveCustomerByStoreId 将不需要,因为如果它与商店相关,则商店存储库有责任提供它。

    总而言之,如果你遵循 DDD,传递查询只会让设计变得非常草率。

    【讨论】:

    • 我的老板 = 来自“Variant VB6 COM”时代。他甚至争论为什么我们应该有 3 层。他说这使得解决问题的时间增加了 3 倍。虽然我当然说相反。现在你明白他为什么要在客户端构建查询,将它们传递给服务。服务执行提供的查询,应用一些逻辑并将数据发回。我真的必须和我的老板回归基础。简单地说我们会破坏 DDD 对他来说不是一个论据。忘记你所知道的关于编程的一切。现在...告诉我为什么我们不应该将 SQL 查询(作为字符串)作为参数提供给服务。
    【解决方案2】:

    您是否考虑过使用 WCF 数据服务? http://msdn.microsoft.com/en-us/library/cc668794.aspx

    【讨论】:

    • @Jean-Christophe Fortin:
      是的,我有。但是数据库还没有为实体框架做好准备(我发现 WCF 数据服务与 EF 结合起来最有用),而且我们还希望在服务器端使用业务逻辑。
    【解决方案3】:

    这是 SOAP 样式的 WCF 服务吗?还是 RESTful 的?

    无论哪种方式,我都希望有一组可选参数,您可以通过这些参数发出请求,因此以 RESTful 服务为例,您将有一组额外的查询字符串参数来检索客户.

    例如:

    /Customers?id=ID /客户?名称=名称 /Customers?StoreId=STORE /Customers?id=ID&withPersonalDetails=true&withPersonalDetails=false

    当然,如果您主要通过 ID 获取,那么

    /客户/{id}/

    将是一个很好的服务 URL。

    等效的东西可以在 SOAPy 端工作,请求中有一堆可以为空的参数。

    优点是客户只需要知道它对客户的了解,并且可以将其提供给服务,这可以解决更复杂的任务,即在检索客户之前确定查询需要什么。缺点是客户可能会提出无法提供足够信息来吸引客户的请求。

    但至少您不必担心客户端提供无效查询。

    编辑:

    至于为什么让客户提供查询是个坏主意——简短的回答是“它破坏了encapsulation,并引入了很多coupling”。长答案是客户端现在依赖于服务的实现细节。假设数据库的布局发生了变化,理想情况下您希望尽可能少地进行更改——在一个封装良好的系统中,您必须更新持久层,可能没有别的。如果您的客户需要了解架构,您必须从头到尾更新所有层,这显然很糟糕。

    其次,如果客户提供查询,您就在暗中信任客户 - 您手头有很大的工作要限制客户可以做的事情 - 想想如果有人开始冒充您的客户并任意运行会发生什么针对您的数据库的查询 - eek!

    第三,如果您需要修复查询,如果它在客户端中,您必须更新客户端代码并将更新推送到所有客户端(有些可能不接受,让这些用户留下错误)如果它被封装在服务中,您只需在那里解决问题。

    第四,您的业务规则现在在哪里执行?在客户端。通过客户端和数据库之间的服务,您的所有业务规则都在一个地方,您可以很好地控制。

    如果您的客户正在制作数据库查询,那么它也可以直接附加到数据库 - 这在许多情况下都很好。但是,如果您希望能够在服务背后抽象数据库访问,在一个地方更新/修复您的业务规则,并限制您对恶意客户端的责任,那么这是一个非常糟糕的主意。

    (我敢肯定还有很多其他原因,在我早上喝茶之前,这些都在我脑海中浮现。)

    【讨论】:

    • 如果它是一个 SOAP 服务,你可以有一个参数,它接受一个“SearchParameters”对象,整个搜索都被很好地定义了。
    • @Massif:
      首先感谢您的回复,但很抱歉。是 SOAP 还是 RESTfull 对于本次讨论并不重要。请参阅我对 Aliostad 的回复。让我为您更清楚地说明问题。我的老板想做这样的事情: /Customers?query="SELECT * FROM Customer WHERE ID = 1" 这在很多层面上都打破了所有常见的做法,但我们想要争论为什么我们不应该这样做。那么,您认为我们为什么不这样做呢? @Tridus:
      你和 Massif 一样。谢谢你的回复。请查看我写给 Aliostad 和 Massif 的内容。
    【解决方案4】:

    所以他的想法是让客户端构建查询并将其发送到 WCF 服务。 WCF 服务执行查询、应用业务逻辑并返回结果。

    它被称为Specification Pattern,在DDD中经常使用。

    一个接受规范参数的服务方法足以处理 95% 的对象请求。

    WCF RIA Services 中的EntityQuery 类是一个示例,说明如何在客户端服务架构中使用规范模式。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2011-11-12
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-02-15
      相关资源
      最近更新 更多