bool SaveInternal(Type actualType, Type tableType, object instance, CycleCache cache, out object key) { if (!this.TableDefinitions.TryGetValue(tableType, out ITableDefinition tableDefinition)) { throw new SterlingTableNotFoundException(instance.GetType(), this.Name); } if (!tableDefinition.IsDirty(instance)) { key = tableDefinition.FetchKeyFromInstance(instance); return(false); } // call any before save triggers foreach (var trigger in _TriggerList(tableType).Where(trigger => !trigger.BeforeSave(actualType, instance))) { throw new SterlingTriggerException( Exceptions.Exceptions.BaseDatabaseInstance_Save_Save_suppressed_by_trigger, trigger.GetType()); } key = tableDefinition.FetchKeyFromInstance(instance); int keyIndex; if (cache.Check(instance)) { return(false); } lock (tableDefinition) { if (cache.Check(instance)) { return(false); } cache.Add(tableType, instance, key); keyIndex = tableDefinition.Keys.AddKey(key); } this.Driver.Save(actualType, tableType, instance, keyIndex, cache); // update the indexes foreach (var index in tableDefinition.Indexes.Values) { index.AddIndex(instance, key); } // call post-save triggers foreach (var trigger in _TriggerList(tableType)) { trigger.AfterSave(actualType, instance); } return(true); }
/// <summary> /// Load it without knowledge of the key type /// </summary> /// <param name="type">The type to load</param> /// <param name="key">The key</param> /// <param name="cache">Cache queue</param> /// <returns>The instance</returns> public object Load(Type type, object key, CycleCache cache) { var newType = type; var assignable = false; var keyIndex = -1; if (!this.TableDefinitions.ContainsKey(type)) { // check if type is a base type foreach (var t in this.TableDefinitions.Keys.Where(type.IsAssignableFrom)) { assignable = true; var tableDefinition = this.TableDefinitions[t]; lock (tableDefinition) { keyIndex = tableDefinition.Keys.GetIndexForKey(key); } if (keyIndex < 0) { continue; } newType = t; break; } } else { var tableDefinition = this.TableDefinitions[newType]; lock (tableDefinition) { keyIndex = tableDefinition.Keys.GetIndexForKey(key); } } if (!assignable) { if (!this.TableDefinitions.ContainsKey(type)) { throw new SterlingTableNotFoundException(type, this.Name); } } if (keyIndex < 0) { return(null); } var obj = GetInstance(newType, key, keyIndex, cache); _RaiseOperation(SterlingOperation.Load, newType, key); return(obj); }
/// <summary> /// Save when key is not known /// </summary> /// <param name="actualType">The type of instance to save</param> /// <param name="tableType">The table type to save to</param> /// <param name="instance">The instance</param> /// <param name="cache">Cycle cache</param> /// <returns>The key</returns> public bool Save(Type actualType, Type tableType, object instance, CycleCache cache, out object key) { bool retVal; if (retVal = SaveInternal(actualType, tableType, instance, cache, out key)) { _RaiseOperation(SterlingOperation.Save, tableType, key, instance); } return(retVal); }
/// <summary> /// Gets an instance by key /// </summary> private object GetInstance(Type type, object key, int keyIndex, CycleCache cache) { var obj = cache.CheckKey(type, key); if (obj != null) { return(obj); } if (keyIndex < 0) { return(null); } obj = this.Driver.Load(type, key, keyIndex, cache); return(obj); }
public abstract object Load(Type type, object key, int keyIndex, CycleCache cache);
public abstract void Save(Type actualType, Type tableType, object instance, int keyIndex, CycleCache cache);
/// <summary> /// Load it without knowledge of the key type /// </summary> /// <param name="type">The type to load</param> /// <param name="key">The key</param> /// <param name="cache">Cache queue</param> /// <returns>The instance</returns> public object Load(Type type, object key, CycleCache cache) { var newType = type; var assignable = false; var keyIndex = -1; if (!TableDefinitions.ContainsKey(type)) { // check if type is a base type foreach (var t in TableDefinitions.Keys.Where(type.IsAssignableFrom)) { assignable = true; lock (TableDefinitions[t]) { keyIndex = TableDefinitions[t].Keys.GetIndexForKey(key); } if (keyIndex < 0) { continue; } newType = t; break; } } else { lock (TableDefinitions[newType]) { keyIndex = TableDefinitions[newType].Keys.GetIndexForKey(key); } } if (!assignable) { if (!TableDefinitions.ContainsKey(type)) { throw new SterlingTableNotFoundException(type, Name); } } if (keyIndex < 0) { return(null); } var obj = cache.CheckKey(newType, key); if (obj != null) { return(obj); } BinaryReader br = null; MemoryStream memStream = null; try { br = Driver.Load(newType, keyIndex); var serializationHelper = new SerializationHelper(this, Serializer, SterlingFactory.GetLogger(), s => Driver.GetTypeIndex(s), i => Driver.GetTypeAtIndex(i)); if (_byteInterceptorList.Count > 0) { var bytes = br.ReadBytes((int)br.BaseStream.Length); bytes = _byteInterceptorList.ToArray().Reverse().Aggregate(bytes, (current, byteInterceptor) => byteInterceptor.Load(current)); memStream = new MemoryStream(bytes); br.Close(); br = new BinaryReader(memStream); } obj = serializationHelper.Load(newType, key, br, cache); } finally { if (br != null) { br.Close(); } if (memStream != null) { memStream.Flush(); memStream.Close(); } } _RaiseOperation(SterlingOperation.Load, newType, key); return(obj); }
/// <summary> /// Save when key is not known /// </summary> /// <param name="actualType">The type of instance to save</param> /// <param name="tableType">The table type to save to</param> /// <param name="instance">The instance</param> /// <param name="cache">Cycle cache</param> /// <returns>The key</returns> public object Save(Type actualType, Type tableType, object instance, CycleCache cache) { if (!TableDefinitions.ContainsKey(tableType)) { throw new SterlingTableNotFoundException(instance.GetType(), Name); } if (!TableDefinitions[tableType].IsDirty(instance)) { return(TableDefinitions[tableType].FetchKeyFromInstance(instance)); } // call any before save triggers foreach (var trigger in _TriggerList(tableType).Where(trigger => !trigger.BeforeSave(actualType, instance))) { throw new SterlingTriggerException( Exceptions.Exceptions.BaseDatabaseInstance_Save_Save_suppressed_by_trigger, trigger.GetType()); } var key = TableDefinitions[tableType].FetchKeyFromInstance(instance); int keyIndex; if (cache.Check(instance)) { return(key); } lock (TableDefinitions[tableType]) { if (cache.Check(instance)) { return(key); } cache.Add(tableType, instance, key); keyIndex = TableDefinitions[tableType].Keys.AddKey(key); } var memStream = new MemoryStream(); try { using (var bw = new BinaryWriter(memStream)) { Helper.Save(actualType, instance, bw, cache, true); bw.Flush(); if (_byteInterceptorList.Count > 0) { var bytes = memStream.GetBuffer(); bytes = _byteInterceptorList.Aggregate(bytes, (current, byteInterceptor) => byteInterceptor.Save(current)); memStream = new MemoryStream(bytes); } memStream.Seek(0, SeekOrigin.Begin); Driver.Save(tableType, keyIndex, memStream.ToArray()); } } finally { memStream.Flush(); memStream.Close(); } // update the indexes foreach (var index in TableDefinitions[tableType].Indexes.Values) { index.AddIndex(instance, key); } // call post-save triggers foreach (var trigger in _TriggerList(tableType)) { trigger.AfterSave(actualType, instance); } _RaiseOperation(SterlingOperation.Save, tableType, key); return(key); }