private void SaveAllUpdated(TikEntityMetadata metadata) { for (int i = 0; i < items.Count; i++) { TEntity entity = items[i]; ITikEntityWithId entityAsEntityWithId = ((ITikEntityWithId)entity); if (entity.IsModified) { Dictionary<string, string> valuesToSet = new Dictionary<string, string>(); List<string> propertiesToUnset = new List<string>(); foreach(KeyValuePair<string, string> pair in entity.GetAllModifiedProperties()) { if (pair.Value == null) propertiesToUnset.Add(pair.Key); else valuesToSet.Add(pair.Key, pair.Value); } Logger.InfoFormat("UPDATE: {0}", entity); if (valuesToSet.Count > 0) session.Connector.ExecuteSet(metadata.EntityPath, entityAsEntityWithId.Id, valuesToSet); if (propertiesToUnset.Count > 0) session.Connector.ExecuteUnset(metadata.EntityPath, entityAsEntityWithId.Id, propertiesToUnset); TEntity newEntity = LoadItem(entityAsEntityWithId.Id); items[i] = newEntity; //put saved&loaded entity into list instead of dirty old-one } } }
///// <summary> ///// Gets the id of entity. ///// </summary> ///// <value>The entity id or null for new instance.</value> //[TikProperty(".id", typeof(string), true, TikPropertyEditMode.ReadOnly)] //public string Id //{ // get { return properties.GetAsStringOrNull(".id"); } //} /// <summary> /// See <see cref="ITikEntity.LoadFromEntityRow"/> for details. /// Calls <see cref="OnCustomLoadFromEntityRow"/>. /// </summary> /// <remarks>Sets object state to unmodified by <see cref="MarkClear"/> call!</remarks> public void LoadFromEntityRow(ITikEntityRow entityRow) { //attributes.CreateAttribute(".id", entityRow.GetValue(".Id")); TikEntityMetadata entityMetadata = TikEntityMetadata.Get(GetType()); foreach (KeyValuePair <string, TikPropertyAttribute> propPair in entityMetadata.Properties) { if (propPair.Value.PropertyType == typeof(string)) { Properties.CreatePropertyWithValue(propPair.Key, entityRow.GetStringValueOrNull(propPair.Key, propPair.Value.Mandatory)); } else if ((propPair.Value.PropertyType == typeof(long)) || propPair.Value.PropertyType == typeof(long?)) { Properties.CreatePropertyWithValue(propPair.Key, entityRow.GetInt64ValueOrNull(propPair.Key, propPair.Value.Mandatory)); //long.Parse(entityRow.GetValue(propPair.Key), System.Globalization.CultureInfo.CurrentCulture) } else if ((propPair.Value.PropertyType == typeof(bool)) || (propPair.Value.PropertyType == typeof(bool?))) { Properties.CreatePropertyWithValue(propPair.Key, entityRow.GetBoolValueOrNull(propPair.Key, propPair.Value.Mandatory)); //string.Equals(entityRow.GetValue(propPair.Key), "true", StringComparison.OrdinalIgnoreCase) } else { throw new NotImplementedException(string.Format(CultureInfo.CurrentCulture, "Not supported property '{0}' type '{1}' in {2}.", propPair.Key, propPair.Value.PropertyType, this)); } //catch (FormatException ex) //{ // throw new FormatException(string.Format("Value '{0}' of property '{1}' can not be parsed to type '{2}' in {3}", // entityRow.GetStringValue(propPair.Key), propPair.Key, propPair.Value.PropertyType, this), ex); //} } OnCustomLoadFromEntityRow(entityRow); MarkClear(); }
/// <summary> /// Gets the metadata for specified entity type (if metadata are not present in cache, /// than it reads them by attribute reflection). /// </summary> /// <param name="entityType">Type of the entity.</param> /// <returns>Metadata for given type read by reflection form entity attributes.</returns> public static TikEntityMetadata Get(Type entityType) { Guard.ArgumentNotNull(entityType, "entityType"); TikEntityMetadata result; bool found; lock (lockObj) { found = cache.TryGetValue(entityType, out result); } if (!found) { //resolve out of the lock result = new TikEntityMetadata(entityType); } lock (lockObj) { if (!cache.ContainsKey(entityType)) { cache.Add(entityType, result); } } return(result); }
private void SaveAllDeleted(TikEntityMetadata metadata) { for (int i = items.Count - 1; i >= 0; i--) { TEntity entity = items[i]; if (entity.IsMarkedDeleted) { Logger.InfoFormat("DELETE: {0}", entity); session.Connector.ExecuteDelete(metadata.EntityPath, ((ITikEntityWithId)entity).Id); items.RemoveAt(i); //remove deleted entity from list } } }
private void SaveAllNew(TikEntityMetadata metadata) { for (int i = 0; i < items.Count; i++) //REMARKS msut be (0 -> count) because of order items added to end { TEntity entity = items[i]; if (entity.IsMarkedNew) { Dictionary<string, string> values = entity.GetAllModifiedProperties(); Logger.InfoFormat("CREATE: {0}", entity); string newId = session.Connector.ExecuteCreate(metadata.EntityPath, values); TEntity newEntity = LoadItem(newId); items[i].Assign(newEntity); //put saved&loaded entity DATA (pointer can not be changed) instead of dirty old-ones data } } }
protected Dictionary <string, string> GetAllModifiedProperties() { TikEntityMetadata metadata = TikEntityMetadata.Get(GetType()); Dictionary <string, string> result = new Dictionary <string, string>(); foreach (KeyValuePair <string, TikPropertyAttribute> propPair in metadata.Properties) { bool found; bool modified; bool hasValue; properties.GetPropertyState(propPair.Key, out found, out modified, out hasValue); if ((propPair.Value.EditMode == TikPropertyEditMode.Editable) && found && modified) { string valueAsText; if (!hasValue) { valueAsText = ""; } else { if (propPair.Value.PropertyType == typeof(string)) { valueAsText = properties.GetAsString(propPair.Key); } else if ((propPair.Value.PropertyType == typeof(long)) || propPair.Value.PropertyType == typeof(long?)) { valueAsText = properties.GetAsInt64(propPair.Key).ToString(CultureInfo.InvariantCulture); } else if ((propPair.Value.PropertyType == typeof(bool)) || (propPair.Value.PropertyType == typeof(bool?))) { valueAsText = properties.GetAsBoolean(propPair.Key) ? "yes" : "no"; } else { throw new NotImplementedException(string.Format(CultureInfo.CurrentCulture, "Not supported property '{0}' type '{1}' in {2}.", propPair.Key, propPair.Value.PropertyType, this)); } } result.Add(propPair.Key, valueAsText); } } return(result); }
private void SaveAllMoves(TikEntityMetadata metadata, TikSession session) { Logger.DebugFormat("Going to perform {0} moves.", MovesCount); foreach (KeyValuePair <TEntity, TEntity> pair in entityMoves) { Logger.InfoFormat("MOVE: {0} before {1} ({2} before {3})", Items.IndexOf(pair.Key), Items.IndexOf(pair.Value), pair.Key, pair.Value); if (pair.Value != null) { session.Connector.ExecuteMove(metadata.EntityPath, pair.Key.Id, pair.Value.Id); } else { session.Connector.ExecuteMoveToEnd(metadata.EntityPath, pair.Key.Id); } } entityMoves.Clear(); }
/// <summary> /// Saves this instance (is protected because not all list are savable = <see cref="IEditableTikList"/> - derived class should expose public Save() method.) /// - saves all entities tha are in <see cref="TikEntityBase.IsModified"/>, /// <see cref="TikEntityBase.IsMarkedDeleted"/> and <see cref="TikEntityBase.IsMarkedNew"/> states. /// Uses session from constructor. /// </summary> protected void SaveInternal() { if (typeof(TEntity).GetInterface(typeof(ITikEntityWithId).Name) == null) throw new NotSupportedException("TEntity must be of ITikEntityWithId type when usign SaveInternal method."); TikEntityMetadata metadata = TikEntityMetadata.Get(typeof(TEntity)); logger.DebugFormat("Going to save {0}/{1}/{2} new/update/delete items.", NewCount, UpdatedCount, DeletedCount); SaveAllNew(metadata); //must be before position change!!! AfterSaveAllNew(metadata, session); SaveAllUpdated(metadata); AfterSaveAllUpdated(metadata, session); SaveAllDeleted(metadata); // must be after position changes AfterSaveAllDeleted(metadata, session); logger.Debug("Successfully saved."); }
private List<TEntity> LoadItemsInternal(TikConnectorQueryFilterDictionary filter, TikSession session) { List<TEntity> result = new List<TEntity>(); TikEntityMetadata entityMetadata = TikEntityMetadata.Get(typeof(TEntity)); IEnumerable<ITikEntityRow> response; if (filter != null) response = session.Connector.ExecuteReader(entityMetadata.EntityPath, entityMetadata.ReaderBehavior, entityMetadata.PropertyNames, filter); else response = session.Connector.ExecuteReader(entityMetadata.EntityPath, entityMetadata.ReaderBehavior, entityMetadata.PropertyNames); VerifyResponseRows(response); foreach (ITikEntityRow entityRow in response) { TEntity item = new TEntity(); item.LoadFromEntityRow(entityRow); result.Add(item); } logger.DebugFormat("{0} items loaded.", result.Count); return result; }
/// <summary> /// Gets the metadata for specified entity type (if metadata are not present in cache, /// than it reads them by attribute reflection). /// </summary> /// <param name="entityType">Type of the entity.</param> /// <returns>Metadata for given type read by reflection form entity attributes.</returns> public static TikEntityMetadata Get(Type entityType) { Guard.ArgumentNotNull(entityType, "entityType"); TikEntityMetadata result; bool found; lock(lockObj) { found = cache.TryGetValue(entityType, out result); } if (!found) { //resolve out of the lock result = new TikEntityMetadata(entityType); } lock(lockObj) { if (!cache.ContainsKey(entityType)) cache.Add(entityType, result); } return result; }
/// <summary> /// See <see cref="TikListBase{TEntity}.AfterSaveAllNew"/>. /// Additionaly save all moves to mikrotik (see <see cref="ITikConnector.ExecuteMove"/>). /// </summary> protected override void AfterSaveAllNew(TikEntityMetadata metadata, TikSession session) { base.AfterSaveAllNew(metadata, session); SaveAllMoves(metadata, session); }
protected virtual void AfterSaveAllDeleted(TikEntityMetadata metadata, TikSession session) { //dummy }