我正在使用Microsoft的新
Universal Providers在sql Server中进行会话. sql Server上的旧会话实现需要一个作业(每分钟运行一次)来清除过期的会话.新的一个检查并清除每个请求.由于我实际上是在sql Azure中运行,因此我没有sql Agent来安排作业,所以这听起来像是一种合理的方式(不,我不想为会话支付Azure Cache).
问题是当多个用户同时访问该站点时,他们都试图同时清除相同的过期会话,第二个获得乐观的并发异常.
System.Data.OptimisticConcurrencyException: Store update,insert,or delete statement affected an unexpected number of rows (0). Entities may have been modified or deleted since entities were loaded. Refresh ObjectStateManager entries. at System.Data.Mapping.Update.Internal.UpdateTranslator.Update(IEntityStateManager stateManager,IEntityAdapter adapter) at System.Data.Objects.ObjectContext.SaveChanges(SaveOptions options) at System.Web.Providers.DefaultSessionStateProvider.PurgeExpiredSessions() at System.Web.Providers.DefaultSessionStateProvider.PurgeIfNeeded() at System.Web.SessionState.SessionStateModule.BeginAcquireState(Object source,EventArgs e,AsyncCallback cb,Object exTradata) at System.Web.HttpApplication.AsyncEventExecutionStep.System.Web.HttpApplication.IExecutionStep.Execute() at System.Web.HttpApplication.ExecuteStep(IExecutionStep step,Boolean& completedSynchronously)
我正在使用ELMAH进行错误记录,这显示出一些频率.在我尝试配置ELMAH以忽略错误之前,有没有人知道一种方法来阻止错误发生在第一位?是否有一些我缺少的新提供商的配置?
解决方法
这个包有一个我称之为bug的东西.进程外会话状态的前提是多个实例可能正在管理会话状态清理.在这种情况下,所有实例都在运行此方法……
private void PurgeExpiredSessions() { using (SessionEntities entities = ModelHelper.CreateSessionEntities(this.ConnectionString)) { foreach (SessionEntity entity in QueryHelper.GetExpiredSessions(entities)) { entities.DeleteObject(entity); } entities.SaveChanges(); this.LastSessionPurgeTicks = DateTime.UtcNow.Ticks; } }
问题是一个实例在其他实体和实体抛出帖子中描述的错误之前删除实体.我要求包作者发布源代码或修复此问题.我未经测试的文本编辑器修复将添加公共虚拟,因此可以覆盖该方法或只是更改它.
private void PurgeExpiredSessions() { using (SessionEntities entities = ModelHelper.CreateSessionEntities(this.ConnectionString)) { var sqlCommand = @"DELETE dbo.Sessions WHERE Expires < GETUTCDATE()"; entities.ExecuteStoreCommand(sqlCommand); this.LastSessionPurgeTicks = DateTime.UtcNow.Ticks; } }
包的作者非常快速地回复(在发布时回答!)今天他们表示他们正在努力发布代码,但他们可能能够解决这个问题.我要求ETA,如果我拿到ETA,我会尝试跟进.
很棒的包装,只需要一点维护.
正确答案:等待源代码发布或修复更新.或者自行解编译并修复(如果这与许可证一致!)
*更新包主人正在考虑本周修复它.是啊!
** Update.soLVED!他们显然已经修复了一段时间,我正在安装错误的包装..
我使用的是http://nuget.org/packages/System.Web.Providers,我本应该使用http://nuget.org/packages/Microsoft.AspNet.Providers/ ..对我而言,哪一个是遗产并包含在另一个包中并不明显.他们把它包裹在一个空的渔获..
private void PurgeExpiredSessions() { try { using (SessionEntities entities = ModelHelper.CreateSessionEntities(this.ConnectionString)) { foreach (SessionEntity entity in QueryHelper.GetExpiredSessions(entities)) { entities.DeleteObject(entity); } entities.SaveChanges(); this.LastSessionPurgeTicks = DateTime.UtcNow.Ticks; } } catch { } }