Example #1
0
        /// <summary>
        ///     Optimistic synchronization using a timestamp property
        ///     Works like an UpdateIf that checks the previous value of a property of type DateTime named "Timestamp"
        ///     It also updates this property withe DateTime.Now
        ///     If you use this you should never modify the timestamp manually
        /// </summary>
        /// <param name="newValue"></param>
        public void UpdateWithTimestampSynchronization(T newValue)
        {
            var prop = newValue.GetType().GetProperty("Timestamp");

            if (prop == null)
            {
                throw new CacheException($"No Timestamp property found on type {typeof(T).Name}");
            }

            if (!prop.CanWrite)
            {
                throw new CacheException($"The Timestamp property of type {typeof(T).Name} is not writable");
            }

            var oldTimestamp = prop.GetValue(newValue);

            var kv = KeyInfo.ValueToKeyValue(oldTimestamp,
                                             new KeyInfo(KeyDataType.IntKey, KeyType.ScalarIndex, "Timestamp"));

            var q        = new AtomicQuery(kv);
            var andQuery = new AndQuery();

            andQuery.Elements.Add(q);
            var orq = new OrQuery(typeof(T));

            orq.Elements.Add(andQuery);

            var now          = DateTime.Now;
            var newTimestamp = now.AddTicks(1); // add one to be sure its different


            prop.SetValue(newValue, newTimestamp);

            _client.UpdateIf(newValue, orq);
        }
Example #2
0
        /// <summary>
        ///     Create a <see cref="KeyValue" />. Ensures conversion from all integer types and <see cref="DateTime" /> to long int
        ///     The default DateTime conversion ignores the time
        /// </summary>
        /// <param name="instance"> the object containing the key </param>
        /// <returns>
        ///     value encoded as <see cref="KeyValue" />
        /// </returns>
        public KeyValue GetValue(object instance)
        {
            if (instance == null)
            {
                throw new ArgumentNullException(nameof(instance));
            }

            var value = _propertyInfo.GetValue(instance, null);

            return(KeyInfo.ValueToKeyValue(value, AsKeyInfo));
        }
Example #3
0
        /// <summary>
        ///     Create a <see cref="KeyValue" />. Ensures conversion from all integer types and <see cref="DateTime" /> to long int
        ///     The default DateTime conversion ignores the time
        /// </summary>
        /// <param name="instance"> the object containing the key </param>
        /// <returns>
        ///     value encoded as <see cref="KeyValue" />
        /// </returns>
        public KeyValue GetValue(object instance)
        {
            //TODO use precompiled accessors
            if (instance == null)
            {
                throw new ArgumentNullException(nameof(instance));
            }

            var value = Info.GetValue(instance, null);

            return(KeyInfo.ValueToKeyValue(value, AsKeyInfo));
        }
Example #4
0
        /// <summary>
        ///     Get the values in a an IEnumerable property
        /// </summary>
        /// <param name="instance"></param>
        /// <returns></returns>
        public IEnumerable <KeyValue> GetCollectionValues(object instance)
        {
            if (instance == null)
            {
                throw new ArgumentNullException(nameof(instance));
            }

            if (!(Info.GetValue(instance, null) is IEnumerable values))
            {
                throw new NotSupportedException($"Property {Info.Name} can not be converted to IEnumerable");
            }

            return((from object value in values select KeyInfo.ValueToKeyValue(value, AsKeyInfo)).ToList());
        }
Example #5
0
        /// <summary>
        ///     Parse a string like "key == value" or "key &gt; value"
        /// </summary>
        /// <param name="queryString"></param>
        /// <returns></returns>
        private AtomicQuery StringToQuery(string queryString)
        {
            var expression = new Regex("(\\w+)\\s*(==|=|<=|<|>|>=|CONTAINS)\\s*((\\w|-|\\.)+)");
            var match      = expression.Match(queryString);

            if (!match.Success || match.Captures.Count != 1 || match.Groups.Count != 5)
            {
                throw new ArgumentException($"Invalid query string {queryString}");
            }


            var left = match.Groups[1].Value;

            left = left.Trim();
            var oper = match.Groups[2].Value;

            oper = oper.Trim();
            var right = match.Groups[3].Value;

            right = right.Trim();

            KeyInfo keyInfo = null;

            if (_typeDescription.PrimaryKeyField.Name.ToUpper() == left.ToUpper())
            {
                keyInfo = _typeDescription.PrimaryKeyField;
            }

            if (keyInfo == null)
            {
                foreach (var uniqueField in _typeDescription.UniqueKeyFields)
                {
                    if (uniqueField.Name.ToUpper() == left.ToUpper())
                    {
                        keyInfo = uniqueField;
                    }
                }
            }

            if (keyInfo == null)
            {
                if (_typeDescription.IndexFields != null)
                {
                    foreach (var indexField in _typeDescription.IndexFields)
                    {
                        if (indexField.Name.ToUpper() == left.ToUpper())
                        {
                            keyInfo = indexField;
                        }
                    }
                }
            }

            if (keyInfo == null)
            {
                foreach (var indexField in _typeDescription.ListFields)
                {
                    if (indexField.Name.ToUpper() == left.ToUpper())
                    {
                        keyInfo = indexField;
                    }
                }
            }

            if (keyInfo == null)
            {
                throw new ArgumentException(left + " is not an index field");
            }


            KeyValue keyValue;

            if (keyInfo.KeyDataType == KeyDataType.IntKey)
            {
                // special processing for dates(must be in yyyy-mm-dd format)
                var parts = right.Split('-');
                if (parts.Length == 3)
                {
                    var date = DateTime.Parse(right);

                    keyValue = new KeyValue(date.Ticks, keyInfo);
                }
                else
                {
                    if (right.Contains(".")) // floating point value
                    {
                        if (!decimal.TryParse(right, out var floatValue))
                        {
                            throw new ArgumentException(right + " can not be converted to float");
                        }

                        keyValue = KeyInfo.ValueToKeyValue(floatValue, keyInfo);
                    }
                    else // integer value
                    {
                        if (!long.TryParse(right, out var longValue))
                        {
                            throw new ArgumentException(right + " can not be converted to long");
                        }


                        keyValue = KeyInfo.ValueToKeyValue(longValue, keyInfo);
                    }
                }
            }
            else
            {
                keyValue = new KeyValue(right, keyInfo);
            }


            QueryOperator op;

            switch (oper.ToLower())
            {
            case "=":
            case "==":
                op = QueryOperator.Eq;
                break;

            case "<":
                op = QueryOperator.Lt;
                break;

            case "<=":
                op = QueryOperator.Le;
                break;

            case ">":
                op = QueryOperator.Gt;
                break;

            case ">=":
                op = QueryOperator.Ge;
                break;

            case "CONTAINS":
                op = QueryOperator.In;
                break;

            default:
                throw new ArgumentException("unknown operator: ", oper);
            }

            var result = new AtomicQuery(keyValue, op);

            return(result);
        }