コード例 #1
0
ファイル: AtomicIncrement.cs プロジェクト: ren85/linqdb
        //public void AtomicIncrement<T, TKey>(IDbQueryable<T> source, Expression<Func<T, TKey>> keySelector, int value, T item) where T : new()
        //{
        //    if (item == null)
        //    {
        //        throw new LinqDbException("Linqdb: new_item_if_doesnt_exist can't be null");
        //    }
        //    var table_info = CheckTableInfo<T>();

        //    ulong where_hash = GetWhereHash(typeof(T).Name, source.LDBTree);
        //    bool done = false;
        //    string error = null;
        //    var ilock = ModifyBatch.GetTableIncrementBatchLock(typeof(T).Name);
        //    lock (ilock)
        //    {
        //        if (!ModifyBatch._increment_batch.ContainsKey(where_hash))
        //        {
        //            ModifyBatch._increment_batch[where_hash] = new IncrementData()
        //            {
        //                Callbacks = new List<Action<string>>(),
        //                NewObject = item,
        //                Value = 0,
        //                ValueIfNew = 0
        //            };
        //        }
        //        else
        //        {
        //            ModifyBatch._increment_batch[where_hash].ValueIfNew += value;
        //        }
        //        ModifyBatch._increment_batch[where_hash].Value += value;
        //        ModifyBatch._increment_batch[where_hash].Callbacks.Add(f =>
        //        {
        //            done = true;
        //            error = f;
        //        });
        //    }

        //    var _write_lock = GetTableWriteLock(typeof(T).Name);

        //    bool lockAcquired = false;
        //    int maxWaitMs = 60000;
        //    IncrementData _increment_data = null;
        //    try
        //    {
        //        DateTime start = DateTime.Now;
        //        while (!done)
        //        {
        //            lockAcquired = Monitor.TryEnter(_write_lock, 0);
        //            if (lockAcquired)
        //            {
        //                if (done)
        //                {
        //                    Monitor.Exit(_write_lock);
        //                    lockAcquired = false;
        //                    break;
        //                }
        //                else
        //                {
        //                    break;
        //                }
        //            }
        //            Thread.Sleep(250);
        //            //if ((DateTime.Now - start).TotalMilliseconds > maxWaitMs)
        //            //{
        //            //    throw new LinqDbException("Linqdb: AtomicIncrement waited too long to acquire write lock. Is the load too high?");
        //            //}
        //        }
        //        if (done)
        //        {
        //            if (!string.IsNullOrEmpty(error))
        //            {
        //                throw new LinqDbException(error);
        //            }
        //            else
        //            {
        //                return;
        //            }
        //        }

        //        //not done, but have write lock for the table
        //        lock (ilock)
        //        {
        //            _increment_data = ModifyBatch._increment_batch[where_hash];
        //            var oval = new IncrementData();
        //            ModifyBatch._increment_batch.TryRemove(where_hash, out oval);
        //        }


        //        var par = keySelector.Parameters.First();
        //        var name = SharedUtils.GetPropertyName(keySelector.Body.ToString());

        //        int total = 0;
        //        var res = this.SelectEntity<T>(source.LDBTree, out total);
        //        if (res != null && res.Count() > 1)
        //        {
        //            throw new LinqDbException("Linqdb: more than one item identified");
        //        }
        //        if (res == null || !res.Any())
        //        {
        //            var initial = (int)_increment_data.NewObject.GetType().GetProperty(name).GetValue(_increment_data.NewObject, null);
        //            _increment_data.NewObject.GetType().GetProperty(name).SetValue(_increment_data.NewObject, initial + _increment_data.ValueIfNew);
        //            this.SaveIncrement<T>((T)_increment_data.NewObject, null);
        //        }
        //        else
        //        {
        //            if (name == "Id")
        //            {
        //                throw new LinqDbException("Linqdb: can't modify Id property");
        //            }
        //            object ov = typeof(T).GetProperty(name).GetValue(res[0], null);
        //            if (ov == null || !(ov is int))
        //            {
        //                throw new LinqDbException("Linqdb: property to increment must be of type int");
        //            }
        //            int old_val = (int)ov;
        //            int id = (int)typeof(T).GetProperty("Id").GetValue(res[0], null);
        //            var dic = new Dictionary<int, int?>() { { id, old_val + _increment_data.Value } };
        //            UpdateIncrement(keySelector, dic, null);
        //        }
        //        foreach (var cb in _increment_data.Callbacks)
        //        {
        //            cb(null);
        //        }
        //    }
        //    catch (Exception ex)
        //    {
        //        if (_increment_data != null)
        //        {
        //            var additionalInfo = ex.Message;
        //            if (_increment_data.Callbacks.Count() > 1)
        //            {
        //                additionalInfo += " This error could belong to another entity which happened to be in the same batch.";
        //            }
        //            foreach (var cb in _increment_data.Callbacks)
        //            {
        //                cb(additionalInfo);
        //            }
        //        }
        //        throw;
        //    }
        //    finally
        //    {
        //        if (lockAcquired)
        //        {
        //            Monitor.Exit(_write_lock);
        //        }
        //    }
        //}

        public void AtomicIncremen2Props <T, TKey1, TKey2>(IDbQueryable <T> source, Expression <Func <T, TKey1> > keySelector1, Expression <Func <T, TKey2> > keySelector2, int value1, int value2, T item) where T : new()
        {
            if (item == null)
            {
                throw new LinqDbException("Linqdb: new_item_if_doesnt_exist can't be null");
            }
            var table_info  = CheckTableInfo <T>();
            var _write_lock = GetTableWriteLock(typeof(T).Name);

            lock (_write_lock)
            {
                var statistics = new LinqdbSelectStatisticsInternal();
                var res        = this.SelectEntity <T>(source.LDBTree, statistics);
                if (res != null && res.Count() > 1)
                {
                    throw new LinqDbException("Linqdb: more than one item identified");
                }
                if (res == null || !res.Any())
                {
                    this.SaveIncrement <T>(item, null);
                }
                else
                {
                    //prop1
                    var par1  = keySelector1.Parameters.First();
                    var name1 = SharedUtils.GetPropertyName(keySelector1.Body.ToString());
                    if (name1 == "Id")
                    {
                        throw new LinqDbException("Linqdb: can't modify Id property");
                    }
                    object ov = typeof(T).GetProperty(name1).GetValue(res[0], null);
                    if (ov == null || !(ov is int))
                    {
                        throw new LinqDbException("Linqdb: property to increment must be of type int");
                    }
                    int old_val = (int)ov;
                    int id      = (int)typeof(T).GetProperty("Id").GetValue(res[0], null);
                    var dic     = new Dictionary <int, int?>()
                    {
                        { id, old_val + value1 }
                    };
                    UpdateIncrement(keySelector1, dic, null);

                    //prop2
                    var par2  = keySelector2.Parameters.First();
                    var name2 = SharedUtils.GetPropertyName(keySelector2.Body.ToString());
                    if (name2 == "Id")
                    {
                        throw new LinqDbException("Linqdb: can't modify Id property");
                    }
                    ov = typeof(T).GetProperty(name2).GetValue(res[0], null);
                    if (ov == null || !(ov is int))
                    {
                        throw new LinqDbException("Linqdb: property to increment must be of type int");
                    }
                    old_val = (int)ov;
                    dic     = new Dictionary <int, int?>()
                    {
                        { id, old_val + value2 }
                    };
                    UpdateIncrement(keySelector2, dic, null);
                }
            }
        }
コード例 #2
0
 public static IDbQueryable <T> Or <T>(this IDbQueryable <T> source)
 {
     source.LDBTree.Prev.OrWith = source.LDBTree.Prev.Id + 1;
     return(source);
 }