/// <summary> /// Reload the content of a table into the cache /// </summary> /// <param name="database"></param> /// <param name="customerId"></param> /// <param name="table"></param> public void Reload(DatabaseContext database, int customerId, string table) { if (!_enable) { return; } // Check if the reload data is possible if (!_tick.ContainsKey(customerId) || !_tables.ContainsKey(table) || !_records.ContainsKey(customerId)) { return; } // Clean up cache of the table Dictionary <string, Dictionary <int, Tuple <DSRecord, InformationRecord> > > currentCache = _records[customerId]; if (!currentCache.ContainsKey(table)) { return; } Debug($"Reloading table '{table}' into the cache for the customer '{customerId}' ..."); Dictionary <int, Tuple <DSRecord, InformationRecord> > currentCacheTable = currentCache[table]; currentCacheTable.Clear(); // Update the content of the cache DSTable currentTable = _tables[table]; foreach (Tuple <DSRecord, InformationRecord> record in currentTable.ReadRecords(database, customerId)) { currentCacheTable[record.Item1.Id] = record; } Info($"[{customerId}] {currentCacheTable.Count} records read into the table '{table}'"); GC.Collect(); }
/// <summary> /// Build the schema by introspection (tables, columns and properties) /// </summary> /// <param name="schema">Type of DbContext</param> /// <param name="request"></param> public DSDatabase(Type schema, IDSRequest request) { Schema = schema; Tables = new Dictionary <string, DSTable>(); _request = request; if (schema.IsSubclassOf(typeof(DbContext))) { // Each table is described by a DbSet<> object foreach (PropertyInfo property in schema.GetProperties()) { // Only DbSet<X> contains a table if (!property.PropertyType.IsGenericType || property.PropertyType.GetGenericTypeDefinition() != typeof(DbSet <>)) { continue; } // Ignore private, protected tables or properties started with "_" if (property.Name.StartsWith("_") || property.PropertyType.IsNotPublic) { continue; } // Ignore record not inheritence of DSRecord if (!property.PropertyType.GetGenericArguments().First().IsSubclassOf(typeof(DSRecord))) { continue; } DSTable table = new DSTable(this, property, property.PropertyType.GetGenericArguments().First()); Tables[table.Name] = table; } } }
/// <summary> /// Check if the last tick loaded is different, and only load differences ... /// </summary> /// <param name="database"></param> /// <param name="customerId"></param> /// <param name="getDatabase"></param> public void UpdateCache(DatabaseContext database, int customerId, FunctionGetDatabase getDatabase) { if (!_enable) { return; } // Check if the customer is currently loaded if (!_tick.ContainsKey(customerId)) { Initialize(database, customerId, getDatabase); } // the current customer is available Lock(customerId); // lock critical section // If the tick into the cache is not the same as the current one ... update the cache manager int currentTick = GetTick(database, customerId); int previousTick = _tick[customerId]; if (currentTick <= previousTick) { Unlock(customerId); // unlock critical section return; } Debug($"[{customerId}] Updating cache between {previousTick} and {currentTick} ..."); int nbUpdates = 0; try { // Load all records between the last tick and the new one (only for request successfully executed) DSTable currentTable = null; Dictionary <int, Tuple <DSRecord, InformationRecord> > currentContent = null; foreach (RequestTableRecord request in database._RequestTable.Where(r => r.CustomerId == customerId && r.Id != null && previousTick < r.Tick && r.Tick <= currentTick).ToList().OrderBy(r => r.Table).ThenBy(r => r.Id)) { // new table ? if (currentTable == null || !currentTable.Name.Equals(request.Table)) { currentTable = null; currentContent = null; if (!_tables.ContainsKey(request.Table)) { if (IsVerbose()) { Verbose($"[{customerId}] The table '{request.Table}' doesn't exist into the cache. May be, the table doesn't exist into the schemas"); } continue; } currentTable = _tables[request.Table]; currentContent = _records[customerId][request.Table]; } // read the current record Tuple <DSRecord, InformationRecord> currentRecord = currentTable.GetRecord(database, request.Id.Value, customerId); if (currentRecord == null) { continue; } // Update the cache currentContent[request.Id.Value] = currentRecord; nbUpdates++; } _tick[customerId] = currentTick; } catch (System.Exception ex) { Exception($"[{customerId}] Unable to update the cache", ex); } Info($"[{customerId}] {nbUpdates} records loaded between {previousTick} and {currentTick}"); Unlock(customerId); // Unlock the critical section }