1

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

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

public class DataService : DataService< PortalEntities >

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

我正在尝试的解决方案是在网站上公开另一个 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它抛出一个未实现的异常。

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

4

2 回答 2

1

如果您不需要更改数据服务器的形状或功能,您应该能够简单地转发请求和响应,就像透明的 HTTP 代理一样。您可能需要做的唯一区别是调整服务 URL。由于代理服务将具有与真实服务不同的基本 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 数据服务分层放在另一个之上目前相当困难。“服务器”生成的 LINQ 表达式树并不总是被“客户端”LINQ 提供程序理解。这就是你遇到的。

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

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

于 2010-06-15T07:35:35.290 回答
0

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

  1. 首先,您在绑定到您的 edmx 模型的应用层上创建 WCF 数据服务。
  2. 然后在未绑定到 edmx 模型(自定义)的 Web 层上创建 WCF 数据服务。
  3. 在 Web 层服务中创建对应用层服务的服务引用。
  4. 将实体类型传递给 DataService 通用声明(对于 VB 应该是尖括号,但我无法让它们显示:

        Public MyWebTierService 
        Inherits DataService[MyServiceReference.MyAppTierEntities]
  1. 为 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 层和应用层之间的跟踪丢失了。

可能我们必须在 Web 层上实现 IUpdatable 来解决这个问题。还不确定,所以任何输入都会有用。

希望这可以帮助

于 2011-10-13T12:05:50.280 回答