是否可以通过WCF实现/保留延迟执行?

时间:2013-02-06 08:25:37

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

最初我有一个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调用保留延迟执行?

1 个答案:

答案 0 :(得分:1)

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

  

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

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

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

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

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

使用伪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(...))
    // ...

关于如何实现这样的事情的简单草图。