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);
        }
Beispiel #12
0
 protected virtual void AfterSaveAllDeleted(TikEntityMetadata metadata, TikSession session)
 {
     //dummy
 }