C# wcf决策:一个服务多个合同或多个服务

C# wcf决策:一个服务多个合同或多个服务,c#,wcf,architecture,C#,Wcf,Architecture,我正在使用.NET4为客户创建一个小型客户机-服务器应用程序。我应该创建一个实现多个契约(IInvoice、ippurchase、isalOrder等)的大型服务,还是应该在多个端口上创建多个运行一个契约的服务?我的问题特别关注两种选择的利弊。还有,回答这个问题的常见方式是什么 我真正的困境是,我没有做出这一决定的经验,而且我对wcf的经验不足,因此需要帮助我理解这一决定的技术含义。看来您是在混合使用DataContract和ServiceContract。 您可以有一个ServiceContr

我正在使用.NET4为客户创建一个小型客户机-服务器应用程序。我应该创建一个实现多个契约(IInvoice、ippurchase、isalOrder等)的大型服务,还是应该在多个端口上创建多个运行一个契约的服务?我的问题特别关注两种选择的利弊。还有,回答这个问题的常见方式是什么


我真正的困境是,我没有做出这一决定的经验,而且我对wcf的经验不足,因此需要帮助我理解这一决定的技术含义。

看来您是在混合使用DataContract和ServiceContract。
您可以有一个ServiceContract和多个DataContract,这将非常适合您的需要。

在实时应用程序中,您为每个实体(如发票、采购和销售订单)都有一个服务合同,将有单独的ServiceContract


但是,对于每个服务契约,都会有异构客户端,如Invoice,后台将通过windows应用程序使用netNamedPipeBinding或netTcpBinding调用,同时客户端应用程序需要使用basicHttpBinding或WSHttpBinding调用服务。基本上,您需要为每个服务创建多个端点。

不要创建一个实现n个服务契约的大型服务。这些类型的服务很容易创建,但最终会成为维护的难题,并且无法很好地扩展。另外,如果有一个开发组在竞争签入/签出,那么您将遇到各种各样的代码合并冲突

也不要创建太多的服务。避免使您的服务过于细粒度的陷阱。尝试基于功能创建服务。这些服务公开的方法也不应该是细粒度的。你最好少用一些能做更多事情的方法。通过创建GetUser(userobjectuser),避免创建类似的函数,如GetUserByID(int-ID)、GetUserByName(string-Name)。您将拥有更少的代码、更易于维护和更好的可发现性

最后,不管您做什么,您可能只需要一个端口

更新12/2018
有趣的是,自从我写这篇文章以来,事情发生了多大的变化。现在有了微服务模式,我用聊天API创建了很多服务:)

您应该根据预期的负载、所需的可扩展性和未来的前景做出决定。正如您所写的“面向客户的小型客户机-服务器应用程序”,它并没有给出手头开发的预期用途的清晰概念。比格先生的回答也必须加以考虑


欢迎你提出进一步的问题,并附上有关手头情况的具体数据或细节。谢谢。

您通常会为每个主要实体创建不同的服务,如IInvoice、IPurchase和ISalesOrder


另一个选项是将查询与命令分开。您可以为每个主要实体提供一个命令服务,并实现业务操作,只接受执行操作所需的数据(避免类似CRUD的操作);以及一个查询服务,以客户端所需的格式返回数据。这意味着命令部分使用底层域模型/业务层;而查询服务直接在数据库上操作(绕过业务,查询不需要业务)。这大大简化了您的查询并使其更加灵活(只返回客户端需要的内容)。

事实是,拆分WCF服务或任何服务都是一种平衡行为。原则是,您希望在考虑性能的同时对复杂性保持向下的压力

创建的服务越多,需要编写的配置就越多。此外,还将增加需要在客户端创建和维护的代理类的数量

在一个服务上放置太多ServiceContract将增加生成和使用代理所需的时间。但是,如果您在一个合同上只完成一个或两个操作,那么您将增加系统的复杂性,而不会获得什么好处。这不是一个科学的处方,但一个好的经验法则可以是每个服务合同大约10-20个运营合同

类耦合当然是一个考虑因素,但您真的要处理单独的关注点吗?这取决于您的系统做什么,但大多数系统只处理少数几个关注的领域,因此,将事情拆分实际上可能不会减少那么多类耦合

还有一件事要记住,这一点非常重要,那就是始终使您的方法尽可能通用。WCF处理数据合同是有原因的。DataContracts意味着只要知道DataContracts,就可以向服务器发送任何对象,也可以从服务器发送任何对象

例如,您可能有3个OperationContract:

[OperationContract]
Person GetPerson(string id);

[OperationContract]
Dog GetDog(string id);

[OperationContract]
Cat GetCat(string id);
但是,只要这些都是已知类型,就可以将它们合并到一个操作中,如:

[OperationContract]
IDatabaseRecord GetDatabaseRecord(string recordTypeName, string id);
最后,这是设计服务合同时要考虑的最重要的事情。如果您使用类似DataContract序列化的序列化方法,则这适用于REST


最后,每隔几个月检查一次您的服务合同,删除客户端未使用的操作。这是另一个大的

如果使用部分类/接口文件来避免合并冲突,那么参数“将无法很好地扩展”又如何呢?从技术上讲,这意味着什么?@Askolein…这意味着如果你在一份合同中塞满了太多东西,它可能会成为性能瓶颈以及维护/扩展性难题。谢谢你的回答,但我的问题更多的是“为什么”可能是性能问题,而不是“什么”是性能问题。你说“瓶颈”:我知道在ISS/WCF中,每个web请求都是一个新的服务实例。一个大型服务上的多个请求仍然是多个实例,而不是一个实例