public void Test_CacheInvalidators() { CacheInvalidatorFactory factory; factory = new CacheInvalidatorFactory(); Assert.That(factory.CacheInvalidators, Has.Exactly(2).TypeOf <SecurityQueryCacheInvalidator>()); Assert.That(factory.CacheInvalidators, Has.Exactly(2).TypeOf <SecurityCacheInvalidatorBase <UserEntityPermissionTuple, bool> >()); Assert.That(factory.CacheInvalidators, Has.Exactly(1).TypeOf <ReportToQueryCacheInvalidator>()); Assert.That(factory.CacheInvalidators, Has.Exactly(1).TypeOf <EntityMemberRequestCacheInvalidator>()); Assert.That(factory.CacheInvalidators, Has.Exactly(1).TypeOf <UserRoleRepositoryCacheInvalidator>()); Assert.That(factory.CacheInvalidators, Has.Exactly(1).Property("Name").Matches("PerTenantEntityTypeCacheInvalidator")); Assert.That(factory.CacheInvalidators, Has.Exactly(1).TypeOf <CachingQuerySqlBuilderInvalidator>( )); Assert.That(factory.CacheInvalidators, Has.Exactly(1).TypeOf <CachingQueryRunnerInvalidator>( )); Assert.That(factory.CacheInvalidators, Has.Exactly(1).TypeOf <CachingUserRuleSetProviderInvalidator>( )); Assert.That(factory.CacheInvalidators, Has.Exactly(1).TypeOf <MetadataCacheInvalidator>()); }
internal static void Test_Scenario(StructuredQuery structuredQuery, Action invalidationCallback, bool expectInvalidation) { CachingQuerySqlBuilder cachingQuerySqlBuilder; Mock <IQuerySqlBuilder> mockQuerySqlBuilder; IQuerySqlBuilder querySqlBuilder; QuerySettings settings; QueryBuild queryBuild; IUserRuleSetProvider userRuleSetProvider = MockUserRuleSetProvider( ); settings = new QuerySettings( ); queryBuild = new QueryBuild( ); var cacheInvalidators = new CacheInvalidatorFactory( ).CacheInvalidatorsList_TestOnly; mockQuerySqlBuilder = new Mock <IQuerySqlBuilder>(MockBehavior.Strict); mockQuerySqlBuilder.Setup(x => x.BuildSql(It.IsAny <StructuredQuery>( ), settings)) .Returns <StructuredQuery, QuerySettings>((sq, qs) => { QuerySqlBuilder.IdentifyCacheDependencies(sq, settings); return(queryBuild); }) .Verifiable( ); querySqlBuilder = mockQuerySqlBuilder.Object; cachingQuerySqlBuilder = new CachingQuerySqlBuilder(querySqlBuilder, userRuleSetProvider); try { // Add current cache invalidator to global factory cacheInvalidators.Add(cachingQuerySqlBuilder.CacheInvalidator); using (var scope = Factory.Current.BeginLifetimeScope(cb => { cb.Register(c => cachingQuerySqlBuilder).As <ICacheService>( ); })) using (Factory.SetCurrentScope(scope)) { // Run first time cachingQuerySqlBuilder.BuildSql(structuredQuery.DeepCopy( ), settings); // Perform potential invalidation task using (new SecurityBypassContext( )) { invalidationCallback( ); } // Run second time cachingQuerySqlBuilder.BuildSql(structuredQuery.DeepCopy( ), settings); } int times = expectInvalidation ? 2 : 1; mockQuerySqlBuilder.Verify(x => x.BuildSql(It.IsAny <StructuredQuery>( ), settings), Times.Exactly(times)); mockQuerySqlBuilder.VerifyAll( ); } finally { // Restore cache invalidators cacheInvalidators.Remove(cachingQuerySqlBuilder.CacheInvalidator); } }
public void Test_CacheInvalidators( ) { CacheInvalidatorFactory factory = new CacheInvalidatorFactory( ); Assert.That(factory.CacheInvalidators, Has.Exactly(1).TypeOf <CachingQuerySqlBuilderInvalidator>( )); Assert.That(factory.CacheInvalidators, Has.Exactly(1).TypeOf <CachingQueryRunnerInvalidator>( )); }
/// <summary> /// Updates the user accounts last logon time. /// </summary> /// <param name="entityId">The entity identifier.</param> /// <remarks> /// This intentionally bypasses the entity model and directly updates the database asynchronously. /// Any cached values are removed from the read-only cache upon completion. /// Cache invalidators are not invoked due to this call. /// </remarks> private static void UpdateUserAccountLastLogon(long entityId) { long tenantId = RequestContext.TenantId; long fieldId = WellKnownAliases.CurrentTenant.LastLogon; DateTime now = DateTime.UtcNow; ThreadPool.QueueUserWorkItem(state => { using (DatabaseContextInfo.SetContextInfo($"Update last logon for user '{entityId}'")) using (DatabaseContext ctx = DatabaseContext.GetContext( )) { using (var command = ctx.CreateCommand("spData_DateTimeMerge", CommandType.StoredProcedure)) { ctx.AddParameter(command, "@entityId", DbType.Int64, entityId); ctx.AddParameter(command, "@tenantId", DbType.Int64, tenantId); ctx.AddParameter(command, "@fieldId", DbType.Int64, fieldId); ctx.AddParameter(command, "@data", DbType.DateTime, now); ctx.AddParameter(command, "@context", DbType.AnsiString, DatabaseContextInfo.GetMessageChain(entityId)); command.ExecuteNonQuery( ); IEntityFieldValues values; ///// // Remove the last logon time from the field cache (if it exists). ///// if (EntityFieldCache.Instance.TryGetValue(entityId, out values)) { object lastLogon; if (values.TryGetValue(fieldId, out lastLogon)) { values [fieldId] = now; } } ///// // Invalidate any items referencing the LastLogon item (NOT the UserAccount item) //// var cacheInvalidators = new CacheInvalidatorFactory( ).CacheInvalidators.ToList( ); List <IEntity> fieldTypes = new List <IEntity> { new IdEntity(fieldId) }; foreach (ICacheInvalidator cacheInvalidator in cacheInvalidators) { cacheInvalidator.OnEntityChange(fieldTypes, InvalidationCause.Save, null); } } } }); }
/// <summary> /// Invalidates the specified identifier. /// </summary> /// <param name="serializableEntityIds">The serializable entity ids.</param> public static void Invalidate(IList <SerializableEntityId> serializableEntityIds) { if (serializableEntityIds == null || serializableEntityIds.Count <= 0) { return; } var invalidators = new CacheInvalidatorFactory( ).CacheInvalidators.ToList(); var list = serializableEntityIds.Select(serializableEntityId => IdEntity.FromId(serializableEntityId.Id, serializableEntityId.TypeIds)).Cast <IEntity>( ).ToList( ); foreach (var invalidator in invalidators) { invalidator.OnEntityChange(list, InvalidationCause.Delete, null); } }
public void Test_CacheInvalidators( ) { CacheInvalidatorFactory factory; factory = new CacheInvalidatorFactory( ); Assert.That(factory.CacheInvalidators, Has.Exactly(1).TypeOf <CachingUserRuleSetProviderInvalidator>( )); Assert.That(factory.CacheInvalidators, Has.Exactly(2).TypeOf <SecurityQueryCacheInvalidator>( )); Assert.That(factory.CacheInvalidators, Has.Exactly(2).TypeOf <SecurityCacheInvalidatorBase <UserEntityPermissionTuple, bool> >( )); Assert.That(factory.CacheInvalidators, Has.Exactly(1).TypeOf <EntityMemberRequestCacheInvalidator>( )); Assert.That(factory.CacheInvalidators, Has.Exactly(1).TypeOf <UserRoleRepositoryCacheInvalidator>( )); }