WCF数据服务 – 代理中间层服务

我们正在开发的项目是一个经典的3层架构。 第1层是数据库服务器,第2层是应用程序服务,第3层是表示层(网站)。

在应用程序服务层中,我有一个项目,其中包括entity framework模型和基于WCF数据服务的服务,该服务公开模型中的实体,例如:

public class DataService : DataService 

这是一个完全成熟的OData服务,可以通过URI查询,例如: /dataservice.svc/mytable?$filter=contains(fieldname,'string') 。 这对于使用jQuery开发任何东西的人来说非常棒,因为他们所要做的就是定义查询。 问题是这项服务是中等级的,因此外界无法看到它。

我正在尝试的解决方案是在网站上公开另一个WCF数据服务,该服务公开由服务引用创建的实体。 如果我向中间层服务添加服务引用,它会为我提供一个数据上下文,在新的WCF数据服务中使用数据上下文:

 public class DataService : DataService 

我必须覆盖CreateDataSource:

 protected override PortalEntities CreateDataSource() { return new PortalEntities(GetMianModelServiceUri()); } 

新服务确实像代理一样运行并返回暴露的实体(查询.../Services/OData/DataService.svc/tbl_Country正常工作)。

但是当一个查询被传递给服务时,例如: .../OData/DataService.svc/tbl_Country?$select=Name它会抛出一个未实现的exception。

有关如何扩展网站服务以使其支持与中间层服务相同的查询的任何想法?

如果您不需要更改数据服务器的形状或function,您应该能够简单地转发请求和响应,就像透明的HTTP代理一样。 您可能需要做的唯一区别是调整服务URL。 由于代理服务将具有与实际服务不同的基URI,因此有效负载将包含实际服务URI(在链接等中),这将不起作用。 您可以通过为您的真实服务使用自定义主机来解决此问题,并对其URI进行说明。 这是通过IDataServiceHost2接口完成的,您从AbsoluteRquestUri和AbsoluteServiceUri属性返回“new”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 。

如果您需要更改形状或function,那么您确实需要真正的分层。

目前,将一个WCF数据服务分层放在另一个上是相当困难的。 “客户端”LINQ提供程序并不总是理解“服务器”生成的LINQ表达式树。 这就是你遇到的。

有一个原型(更像是一个实验)通过重写表达式树在某种程度上使这项工作。 它是OData Provider Toolkit的一部分,您可以在这里下载http://www.odata.org/developers/odata-sdk#/media/7579/odataprovidertoolkit.zip 。 (它位于Experimental文件夹中,AstoriaOverAstoria项目)。

但请注意,这实际上只是一个实验,以显示哪些问题有待解决等等。 我绝对建议不要在任何一种生产环境中使用它。

我发现可以在Web Tier上公开引用App Tier上的服务(而不是直接数据)的服务。 这仅适用于目前的查询。 我不确定需要什么才能让它适用于更新,删除等任何想法? 无论如何,这里有一些说明和代码片段:

  1. 首先,在绑定到edmx模型的App Tier上创建WCF数据服务。
  2. 然后在Web层上创建未绑定到edmx模型(自定义)的WCF数据服务。
  3. 在Web层服务中为App层服务创建服务引用。
  4. 将实体类型传递给DataServicegenerics声明(应该是VB的尖括号,但我无法让它们显示:
 Public MyWebTierService Inherits DataService[MyServiceReference.MyAppTierEntities] 
  1. 为CreateDataSource()添加一个覆盖,创建对App Tier的引用:
 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来解决这个问题。 还不确定,所以任何输入都会有用。

希望这可以帮助