如何使WCF Dataservice停止跟踪实体变更?

9

我有一个web应用程序,通过代理调用OData Web服务( DataServiceContext )。问题是,即使代码每次调用OData Web服务,但在内容管理系统(SDL Tridion)更改内容后,它始终返回旧数据。

<code>string getPageContentForUrl(string url)
{
    var page = cdService
                   .Pages
                   .Expand("PageContent")
                   .Where(x => x.Url == url)
                   .FirstOrDefault();

    if (page == null || page.PageContent == null)
    {
        return string.Empty;
    }
    else
    {
        return page.PageContent.Content;
    }

}
</code>

我们不得不重置应用程序池才能看到最新的数据更改。

所以在更多调试时,我注意到:

var context = (System.Data.Services.Client.DataServiceContext)cdService;
context.Entities[0].State = Unchanged

所以我尝试在从getPageContentForUrl返回值之前显式调用.Detach()来修复它,像这样:

cdService.Detach(page);
cdService.Detach(page.PageContent);

我的问题是,我是否可以在更“全局”的层面上实现以上操作,也许让Web服务始终将状态假定为“已更改”,因为我不想手动编写Detach()代码?

5
我认为不必要分离。可以设置内容传递服务来缓存代理的内容。请打开CDS中的cd_storage_conf.xml,关闭缓存并重试。 - Quirijn
谢谢Quirijn,你能看一下我对Frank答案的评论吗? - parsh
我想你说得对,下面请检查我的答案,看看它是否有帮助。 - Quirijn
2个回答

10
我认为答案确实 - 如您所怀疑的那样 - 在您使用的代理中,或者更确切地说,在DataServiceContext中。这是Microsoft的说法:
  

默认情况下,客户端仅将响应Feed中的条目具象化为对于DataServiceContext未跟踪的实体的对象。这意味着不会覆盖缓存中已有的对象。此行为由为查询和加载操作指定MergeOption值来控制。

在我看来,这听起来就像您所描述的行为。幸运的是,可以通过设置DataServiceContext上的MergeOption属性来关闭缓存。
请参阅http://msdn.microsoft.com/en-us/library/gg602811.aspx

3
是的,问题已经解决了。由于OData WS是只读的,我不得不将MergeOption设置为NoTracking。 - parsh
谢谢!Microsoft.OData.Client.DataServiceContext.MergeOption存在相同的问题,因为它默认为“AppendOnly”。将其设置为context.MergeOption = MergeOption.PreserveChanges解决了我的问题。https://learn.microsoft.com/en-us/dotnet/api/microsoft.odata.client.mergeoption?view=odata-client-7.0 - BateTech

5
正如Quirijn所评论的那样,似乎在您的设置中Tridion内容交付OData服务返回了缓存结果。分离并重新连接客户端是一种强制性的解决方法。
Tridion内容交付对象缓存(在正确配置时)会自动从其缓存中删除通过内容管理系统的发布操作更新的项。由于在您的设置中未发生这种情况,因此您的对象缓存可能未正确配置。
最简单的步骤是找到cd_webservice Web应用程序的cd_storage_conf.xml文件,并关闭对象缓存(正如Quirijn已经说过的那样)。
<ObjectCache Enable="false" />

现在像之前一样回收应用池并进行测试。如果OData调用现在总是返回更新后的内容,那么你的问题确实是由错误配置的对象缓存引起的。
不幸的是,在这个阶段,你所做的只是关闭对象缓存,这肯定会减少web服务的负载处理能力。下一步应该是解决对象缓存的配置问题。
我建议你联系SDL专业服务或SDL的合作伙伴。虽然配置对象缓存并不太困难,但它涉及的内容有点太复杂了,很难在问答形式中解释清楚。

感谢您的回答。我觉得我的问题没有表述清楚,当我在浏览器中发出实际的Odata调用时,我会得到更新后的内容, http://mydomain/odata.svc/Pages()?$filter=Url%20eq%20'%2F100_Simple_Pages%2FFooPage%2FFooPage.html'&$top=1&$expand=PageContent 我们已经实现了一个CacheChannel服务,当发布新数据时,它会清除OData WS缓存。 问题在于代码(getPageContentForUrl)内部调用了使用代理(DataServiceContext)调用OData WS的旧数据。这难道不意味着OData WS设置正确,但代理没有设置好吗? - parsh
啊...如果浏览器显示了更新的内容,那么问题确实必须在客户端。我从未见过生成的代理返回陈旧的内容,所以无法帮忙解决这个问题。 - Frank van Puffelen
Quirijn的建议解决了问题。必须设置MergeOption-请参见我的回答评论。 - parsh

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接