【问题标题】:Is it possible to achieve/preserve deferred execution over WCF?是否可以通过 WCF 实现/保留延迟执行?
【发布时间】:2013-02-06 08:25:37
【问题描述】:

最初我有一个预期延迟执行的 LINQ 查询(比如 EF 或任何其他):

class Provider : IProvider
{
    public IEnumerable<Any> GetSome()
    {
         yield return new Any(); // LINQ query
    }
}

但是现在这样的提供者转移到了 WCF 服务(和 IoC)中:

unityContainer.RegisterType<IProvider>(
    new PerResolveLifetimeManager(),
    new InjectionFactory(c => new ChannelFactory<T>("IService").CreateChannel()));

是否可以通过 WCF 调用保留延迟执行?

【问题讨论】:

  • 您预计会发生什么?客户应该要求每个项目吗?因为这是通过网络延迟执行所需要的。
  • @DanielHilgarth:是的,我想知道是否可以在具体化时轮流请求每个项目。这是一个示例:我有一些繁重的 EF 调用,WCF 客户端必须等待它完成,而不是序列化整个结果集,将其反序列化,然后才开始迭代。从数据库读取/从服务接收,而不是在最后一个结果之前开始处理第一个结果。
  • 那是关于流式传输 - 而不是关于延迟执行......即使使用 WCF 流式传输,它也可能无法正常工作。您必须使用非常低级的 HTTP(分块编码)或 TCP 编程来实现。
  • @LadislavMrnka:我认为这是两个不同的概念。流式传输以服务器规定的速度交付数据。延迟执行以客户设定的速度交付数据。
  • 是的。我误解了你的问题。在这种情况下,这正是@Daniel 所描述的内容,您应该在您的服务上简单地公开GetNext 之类的内容并将枚举包装在您的客户端代码中(您将不得不以某种方式跟踪下一个元素是什么)。

标签: c# wcf linq entity-framework-4 deferred-execution


【解决方案1】:

这个答案实际上是对您对 Ladislav Mrnka 的最后评论的回答。你说:

好的,我明白了,所以不可能有“免费甜甜圈”。在 LINQ to Any 中,我们有这样的行为,但必须跨越服务边界,即要(反)序列化的数据会破坏它,对吗?

虽然它不是免费的,但它仍然是可能的!

在服务器端,您必须一个一个地提供初始化请求的方法和获取结果的方法。

在客户端 - 特别是在其低级基础设施类之一 - 您可以将其包装在枚举器中,最后,您的“业务”类可以像使用其他任何枚举器一样使用该枚举器。

我们已经讨论过,它将在每个项目所需的请求-响应方式中引入额外的开销。这会引入延迟并增加网络负载。

使用伪 RESTful API 的这种方法的示例可能如下所示:

服务器端:

  • POST http://server/api/search-specification:
    正文包含搜索所需的参数,例如开始日期和结束日期
    响应将是一个标识搜索规范的 URI。
  • GET http://server/api/search-specification/1/next-result:
    响应将是下一项。

这个控制器看起来像这样:

public Response PostSearchSpecification(SearchSpecification spec)
{
    int id = _searches.Max(x => x.Key) + 1; // Make thread-safe
    _searches[id] = _provider.GetSome().GetEnumerator();
    return ...;
}

public Item GetNextResult(int searchSpecId)
{
    if(_searches[searchSpecId].MoveNext())
        return _searches.Current;
    else
        return null; // or return a HTTP status code that tells the
                     // client that there are no more items.
}

我称它为伪 RESTful API,因为它看起来确实很像,但它需要在内部保持每个规范的状态以启用延迟执行。另外GET http://server/api/search-specification/1/next-result 不是幂等的。
但我认为它证明了我的意思:)

客户端会这样封装它:

class Search
{
    public IEnumerable<Item> Start(params)
    {
        var client = new HttpClient(...);
        var resultsUri = client.Post(new SearchSpecification(params)).Response;
        Item item = client.Get<Item>(resultsUri);
        while(item != null)
        {
            yield return item;
            item = client.Get<Item>(resultsUri);
        }
    }
}

你会这样使用它:

var search = new Search();

foreach(var item in search.Start(...))
    // ...

只是一个关于如何实现这样的东西的原始草图。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2013-11-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多