2013-07-02 120 views
7

我正在使用.NET 4为客户创建一个小型客户端服务器应用程序。我应该创建一个实现许多合同(IInvoice,IPurchase,ISalesOrder等)的巨型服务,还是应该在许多端口上创建运行一个合同的许多服务?我的问题特别是对任何选择的利弊感兴趣。另外,回答这个问题的常见方法是什么?wcf决定:一个服务多个合同或许多服务

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

回答

4

不要创建一个实现n个服务合约的大型服务。这些类型的服务很容易创建,但最终会成为维护头痛,并且不能很好地扩展。另外,如果有开发组竞争签入/签出,你会得到各种各样的代码合并冲突。

不要创建太多的服务。避免让服务过于细化的陷阱。尝试基于功能创建服务。这些服务暴露的方法也不应该是细粒度的。你最好少做更多的方法。避免通过创建GetUser(userObject用户)来创建类似的函数,如GetUserByID(int ID),GetUserByName(string Name)。您将拥有更少的代码,更轻松的维护和更好的可发现性。

最后,无论你做什么,你都可能只需要一个端口。

+0

如果使用部分类/接口文件来避免合并冲突,那么参数“不能很好地扩展”呢?这在技术上意味着什么? – Askolein

+0

@Askolein ......这意味着如果你在一份合同中填充太多,它可能会成为性能瓶颈以及维护/扩展性问题。 –

+2

感谢您的回答,但我的问题更多的是“为什么”它可能是一个性能问题,而不是“什么”是性能问题。你说“瓶颈”:我明白在ISS/WCF中,每个Web请求都是一个新的Service实例。单个大型服务的多个请求仍然是多个实例,而不是一个实例提供所有这些实例。所以没有缩放问题。这个推理是否正确? – Askolein

1

它似乎是DataContract(s)和ServiceContract(s)之间的混合。 您可以有一个ServiceContract和许多DataContract(s),这将完全适合您的需求。

2

在实时应用中,你有喜欢的发票,购买和SalesOrder每个实体一份服务合同中都会有不同的的ServiceContract

然而,对于每一个服务合同会有异构客户端像发票将通过后台通过Windows应用程序调用使用netNamedPipeBinding或netTcpBinding和相同时间客户端应用程序需要使用basicHttpBinding或wsHttpBindings调用服务。基本上你需要为每个服务创建多个端点。

0

您应该根据预期负载,可扩展性和未来角度来做出决定。正如你写的“面向客户的小型客户服务器应用程序”,它并没有清楚地表明开发的用途。 Big先生的回答也必须考虑。

我们非常欢迎您提出进一步的问题,并提供具体的数据或有关当前情况的详情。谢谢。

2

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

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

0

事实是,分离WCF服务 - 或任何服务是一种平衡行为。原则是你想在考虑业绩的同时保持复杂性的下行压力。

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

将太多ServiceContracts放在一个服务上会增加生成和使用代理所花费的时间。但是,如果您最终只得到一个或两个运营合同,那么您将会增加系统的复杂性,而且几乎没有什么收获。这不是一个科学的处方,但可以说每服务合同10-20 OperationContracts一个好的经验法则。

类耦合当然是一个考虑因素,但是你真的在处理单独的问题吗?这取决于你的系统做什么,但大多数系统只处理少数几个领域的问题,所以分解事情实际上可能不会实际上减少类耦合。

要记住的另一件事,这是非常重要的是总是让你的方法尽可能通用。出于某种原因,WCF在DataContracts中进行交易。 DataContracts意味着只要DataContracts是已知的,您就可以向服务器发送任何对象或从服务器发送对象。

因此,举例来说,你可能有3个OperationContracts:

[OperationContract] 
Person GetPerson(string id); 

[OperationContract] 
Dog GetDog(string id); 

[OperationContract] 
Cat GetCat(string id); 

但是,只要这些都是已知类型的,你可以像合并这些到一个操作:

[OperationContract] 
IDatabaseRecord GetDatabaseRecord(string recordTypeName, string id); 

最终,这是设计服务合同时要考虑的最重要的事情。如果您使用DataContract序列化(如序列化方法),则适用于REST。

最后,每隔几个月回顾一下您的ServiceContracts并删除未被客户使用的操作。这是另一个大的!