从缓存中访问项时,ASP.NET UnauthorizedAccessException

时间:2010-10-28 18:16:27

标签: asp.net caching dynamics-crm

我们有一些代码偶尔刷新ASP.NET缓存中的某些键,以确保我们从Dynamics CRM系统获取最新数据。它似乎在大多数情况下工作正常,但我们在页面重新加载时会出现间歇性异常,我怀疑这与此强制缓存刷新有关。

以下是UnauthorizedAccessException中的错误:

Access to the path 'appDomain=/LM/W3SVC/1/ROOT-1-129326029589946795:key=Microsoft.Xrm.Client.Services.InMemoryCrmCacheProvider:Crm:Query=953227368' is denied.

如果它有用,这就是我如何刷新缓存项目:

 private void Flush()
    {
        IDictionaryEnumerator cacheEnum = this.HttpContext.Cache.GetEnumerator();
        while (cacheEnum.MoveNext())
        {
            var key = cacheEnum.Key.ToString();

            if (key.StartsWith("Microsoft.Xrm.Client.Services.InMemoryCrmCacheProvider:Crm:Query"))
                System.Web.HttpContext.Current.Cache.Remove(key);
        }
    }

我的问题:

  • 访问或删除缓存项是否需要某种级别的权限?我用Google搜索了这个,但没有找到任何具体内容(即使在MSDN中)。
  • 你以前见过这个错误吗?你是怎么解决的?

更新:这是堆栈跟踪。

Stacktrace:
at System.IO.__Error.WinIOError(Int32 errorCode, String maybeFullPath)
at System.Threading.Mutex.MutexTryCodeHelper.MutexTryCode(Object userData)
at System.Runtime.CompilerServices.RuntimeHelpers.ExecuteCodeWithGuaranteedCleanup(TryCode code, CleanupCode backoutCode, Object userData)
at System.Threading.Mutex..ctor(Boolean initiallyOwned, String name, Boolean& createdNew, MutexSecurity mutexSecurity)
at System.Threading.Mutex..ctor(Boolean initiallyOwned, String name, Boolean& createdNew)
at Microsoft.Xrm.Client.Threading.MutexExtensions.Lock(String key, Int32 millisecondsTimeout, Action`1 action)
at Microsoft.Xrm.Client.Threading.MutexExtensions.Get[T](String key, Int32 millisecondsTimeout, Func`2 loadFromCache, Func`2 loadFromService)
at Microsoft.Xrm.Client.Threading.MutexExtensions.Get[T](String key, Func`2 loadFromCache, Func`2 loadFromService, Action`2 addToCache)
at Microsoft.Xrm.Client.Services.InMemoryCrmCacheProvider.InnerExecute[TRequest,TResponse,TResult](TRequest request, Func`2 execute, Func`2 selector, String selectorCacheKey)
at Microsoft.Xrm.Client.Services.CachedOrganizationService.Execute[T](MetadataServiceRequest request, Func`5 execute, Func`2 selector, String selectorCacheKey)
at Microsoft.Xrm.Client.Services.CachedOrganizationService.Execute[T](MetadataServiceRequest request, Func`2 selector, String selectorCacheKey)
at Microsoft.Xrm.Client.Services.CachedOrganizationService.Execute(Object request)
at Microsoft.Xrm.Client.Services.IOrganizationServiceExtensions.RetrieveAllEntities(IOrganizationService service, MetadataItems metadataItems, Boolean retrieveAsIfPublished)
at Microsoft.Xrm.Client.Services.InMemoryCrmCacheProvider.GetId(DynamicEntity entity)
at Microsoft.Xrm.Client.Services.InMemoryCrmCacheProvider.<GetDependencies>d__48.MoveNext()
at Microsoft.Xrm.Client.Services.InMemoryCrmCacheProvider.<GetDependencies>d__41.MoveNext()
at System.Linq.Enumerable.<SelectManyIterator>d__14`2.MoveNext()
at Microsoft.Xrm.Client.Services.InMemoryCrmCacheProvider.<GetDependencies>d__2b.MoveNext()
at Microsoft.Xrm.Client.Services.InMemoryCrmCacheProvider.<GetDependencies>d__13.MoveNext()
at System.Linq.Enumerable.<DistinctIterator>d__81`1.MoveNext()
at Microsoft.Xrm.Client.Services.InMemoryCrmCacheProvider.GetCachePolicy(Object query, Object result)
at Microsoft.Xrm.Client.Services.InMemoryCrmCacheProvider.Insert(String key, Object query, Object result)
at Microsoft.Xrm.Client.Threading.MutexExtensions.<>c__DisplayClass5`1.<Get>b__4(String k)
at Microsoft.Xrm.Client.Threading.MutexExtensions.<>c__DisplayClass2`1.<Get>b__0(Mutex _)
at Microsoft.Xrm.Client.Threading.MutexExtensions.Lock(String key, Int32 millisecondsTimeout, Action`1 action)
at Microsoft.Xrm.Client.Threading.MutexExtensions.Get[T](String key, Int32 millisecondsTimeout, Func`2 loadFromCache, Func`2 loadFromService)
at Microsoft.Xrm.Client.Threading.MutexExtensions.Get[T](String key, Func`2 loadFromCache, Func`2 loadFromService, Action`2 addToCache)
at Microsoft.Xrm.Client.Services.InMemoryCrmCacheProvider.InnerExecute[TRequest,TResponse,TResult](TRequest request, Func`2 execute, Func`2 selector, String selectorCacheKey)
at Microsoft.Xrm.Client.Services.CachedOrganizationService.Execute[T](Request request, Func`2 selector, String selectorCacheKey)
at Microsoft.Xrm.Client.Services.CachedOrganizationService.RetrieveMultiple(QueryBase query)
at Microsoft.Xrm.Client.Services.IOrganizationServiceExtensions.Using[T](Func`1 create, Func`2 action)
at Microsoft.Xrm.Client.Linq.CrmQueryProvider.Execute[TElement](QueryExpression qe, LambdaExpression projection, Delegate postMethodCall, LambdaExpression filter, Type entityType)
at Microsoft.Xrm.Client.Linq.CrmQueryProvider.Execute[TElement](Expression expression)
at Microsoft.Xrm.Client.Linq.QueryProvider.System.Linq.IQueryProvider.Execute[TResult](Expression expression)
at System.Linq.Queryable.Single[TSource](IQueryable`1 source)
at FrontOfficeApp.Controllers.BillingController.GetBillingInstitutions(Requisition req)
at FrontOfficeApp.Controllers.BillingController.InstitutionalBillPartial(Int32 requisitionId)
at lambda_method(Closure , ControllerBase , Object[] )
at System.Web.Mvc.ReflectedActionDescriptor.Execute(ControllerContext controllerContext, IDictionary`2 parameters)
at System.Web.Mvc.ControllerActionInvoker.InvokeActionMethod(ControllerContext controllerContext, ActionDescriptor actionDescriptor, IDictionary`2 parameters)
at System.Web.Mvc.ControllerActionInvoker.<>c__DisplayClassd.<InvokeActionMethodWithFilters>b__a()
at System.Web.Mvc.ControllerActionInvoker.InvokeActionMethodFilter(IActionFilter filter, ActionExecutingContext preContext, Func`1 continuation)
at System.Web.Mvc.ControllerActionInvoker.InvokeActionMethodFilter(IActionFilter filter, ActionExecutingContext preContext, Func`1 continuation)
at System.Web.Mvc.ControllerActionInvoker.InvokeActionMethodWithFilters(ControllerContext controllerContext, IList`1 filters, ActionDescriptor actionDescriptor, IDictionary`2 parameters)
at System.Web.Mvc.ControllerActionInvoker.InvokeAction(ControllerContext controllerContext, String actionName)
at System.Web.Mvc.Controller.ExecuteCore()
at System.Web.Mvc.MvcHandler.<>c__DisplayClass8.<BeginProcessRequest>b__4()
at System.Web.Mvc.Async.AsyncResultWrapper.<>c__DisplayClass1.<MakeVoidDelegate>b__0()
at System.Web.HttpApplication.CallHandlerExecutionStep.System.Web.HttpApplication.IExecutionStep.Execute()
at System.Web.HttpApplication.ExecuteStep(IExecutionStep step, Boolean& completedSynchronously)

Message=Access to the path 'appDomain=/LM/W3SVC/1/ROOT-1-119328537521157948:key=Microsoft.Xrm.Client.Services.InMemoryCrmCacheProvider:Crm:Query=913126368' is denied.
Data=System.Collections.ListDictionaryInternal

UPDATE2: 我们刚刚更新到SDK的4.0.13版本以关闭缓存(实际上我只能通过将持续时间设置为1秒来使其工作,见下文)。这使我们能够解决需要刷新的CRM问题,但我们仍然在我们的环境中遇到缓存错误,尽管它们现在看起来有点不同:

Message=Access to the path 'appDomain=/LM/W3SVC/1/ROOT-1-129341239247458264:key=Microsoft.Xrm.Client.Services.InMemoryCrmCacheProvider:Crm:User=00000000-0000-0000-0000-000000000000,00000000-0000-0000-0000-000000000000:Query=923237368' is denied.
Data=System.Collections.ListDictionaryInternal

对于值得的,我正在使用的上下文配置如下。我正在为这个问题增加一笔赏金,作为最后的尝试。

<microsoft.xrm.client>
    <contexts default="Crm">
        <add name="Crm" type="CRM.XrmDataContext" serviceName="Default" />
    </contexts>
    <services default="Default">
        <add name="Default" cacheProviderName="Default" />
    </services>
    <cache defaultProvider="Default">
        <providers>
            <add name="Default"
               type="Microsoft.Xrm.Client.Caching.InMemoryCacheProvider, Microsoft.Xrm.Client" duration="00:00:01" />
        </providers>
    </cache>
</microsoft.xrm.client>

2 个答案:

答案 0 :(得分:2)

我们终于找到了这个问题的答案。问题与模仿有关(我们在web.config中打开了它)以及我们使用单例访问XRM的事实。显然,当多个用户尝试通过我们的软件同时运行CRM查询时,单例将在其用户上下文中建立与CRM的连接。显然,在发生这种情况时,查询结果的缓存由该用户上下文“拥有”。当另一个用户试图同时运行查询时,他们将收到401状态代码。

修复最终导致模仿并进行一些小的重构,以便我们不再需要它了。我想我们可以允许多个CRM实例 - 尽管出于性能原因我们故意不这样做。

我希望这有助于其他可能会看到这些时髦错误的人。

答案 1 :(得分:0)

我无法想象该异常实际上与 Cache.Remove 调用有关。

只是一个猜测,但是异常可能与 CacheItemRemovedCallback 有关,而不是实际的删除步骤(不确定回调是否在同一个线程上同步执行)?

您可以发布异常的完整堆栈跟踪吗?