WCF数据服务 - 代理中间服务
我们正在开发的项目是一个经典的3层架构。第1层是数据库服务器,第2层是应用程序服务,第3层是表示层(网站)。WCF数据服务 - 代理中间服务
在应用服务层我有一个项目,包括一个实体框架模型和WCF数据服务的基础服务,它暴露了模型如内的实体:
public class DataService : DataService<PortalEntities>
这是一个完全成熟的OData服务,可以通过URI查询,例如:/dataservice.svc/mytable?$filter=contains(fieldname,’string’)
。这对于使用jQuery开发任何东西的人来说非常好,因为他们所要做的就是定义查询。问题在于这项服务是中间层级的,因此外部世界无法看到。
我在尝试的解决方案是公开Web站点上的另一个WCF数据服务,该服务公开由服务引用创建的实体。如果我添加一个服务引用到中间层服务它给了我一个数据上下文数据上下文是在新的WCF数据服务使用:
public class DataService : DataService<PortalEntities>
我必须覆盖的createDataSource:
protected override PortalEntities CreateDataSource()
{
return new PortalEntities(GetMianModelServiceUri());
}
新服务的行为像一个代理,并确实返回实体公开(查询.../Services/OData/DataService.svc/tbl_Country
工作正常)。
但是,当查询传递给服务例如:.../OData/DataService.svc/tbl_Country?$select=Name
它会抛出一个未实现的异常。
关于如何扩展网站服务的任何想法,以便它支持与中间层服务相同的查询?
如果您不需要更改数据服务器的形状或功能,则应该能够简单地转发请求和响应,就像透明的HTTP代理一样。您可能需要做的唯一区别是调整服务网址。由于代理服务将具有与真实服务不同的基本URI,所以有效载荷将包含真实服务URI(在链接等中),这将不起作用。您可以通过为您的真实服务使用自定义主机来解决此问题,并对其URI进行说谎。这是通过IDataServiceHost2接口完成的,您将从AbsoluteRquestUri和AbsoluteServiceUri属性返回“新”URI。界面实现的好例子(尽管用于不同的目的)在这里:http://blogs.msdn.com/b/tom_laird-mcconnell/archive/2010/01/18/using-ado-net-wcf-data-services-for-streaming-infinite-event-result-sets.aspx。
如果您需要更改形状或功能,那么您确实需要真正的分层。
将一个WCF数据服务分层到另一个WCF数据服务目前相当困难。 “服务器”生成的LINQ表达式树并不总能被“客户”LINQ提供者理解。这就是你遇到的问题。
有一个原型(更像是一个实验)在一定程度上通过重写表达式树来完成这项工作。它是OData Provider Toolkit的一部分,您可以在这里下载http://www.odata.org/developers/odata-sdk#/media/7579/odataprovidertoolkit.zip。 (它位于实验文件夹AstoriaOverAstoria项目中)。
但请注意,这实际上只是一个实验来展示哪些问题需要解决,等等。我绝对建议不要在任何类型的生产环境中使用它。
我发现有可能在Web层上暴露一个引用服务(不直接)在应用层上的服务。这只适用于目前的查询。我不确定需要什么才能使它更新,删除等。任何想法的人?无论如何,这里有一些说明和代码片段:
- 首先你在绑定到你的edmx模型的App层上创建一个WCF数据服务。
- 然后在Web层上创建WCF数据服务,而不绑定到edmx模型(自定义)。
- 在Web层服务中创建服务引用到应用层服务。
- 传递实体类型到DataService的一般声明(应该是VB尖括号,但我不能让他们显示:
Public MyWebTierService
Inherits DataService[MyServiceReference.MyAppTierEntities]
- 添加替代了的createDataSource()创建你的参考应用层:
Protected Overrides Function CreateDataSource() As MyServiceReference.MyAppTierEntities
Dim ctx = New MyServiceReference.MyAppTierEntities(New Uri("http://yourappservicelocation/AppService.svc/"))
Return ctx
End Function
你现在要做的就是创建一个参考服务或者其绑定到你的客户端应用程序, 支持OData。如果需要,可以添加JSONP支持。
因此,这适用于查询,但不适用于更新,可能是因为类型不一样(它们可能看起来相同,但在不同的程序集中)。因此,Web和App层之间的跟踪丢失。
这可能是我们必须在Web层上实现IUpdatable来解决这个问题。还不确定,所以任何输入都会有用。
希望这会有所帮助