Example #1
0
        // Tries to enter lock, If retry count over, return false
        public async Task <bool> TableLockTryEnterAsync(TableSetting tableSetting, string primaryKeyValue, int retryCount = 10)
        {
            try
            {
                var db  = this.redis.GetDatabase();
                var key = RedisKey.GetRedisKey_TableLock(tableSetting.tableName, primaryKeyValue);
                var ts  = new TimeSpan(0, 0, 300);

                int count = 0;
                while (!await db.StringSetAsync(key, Thread.CurrentThread.ManagedThreadId.ToString(), ts, When.NotExists))
                {
                    if (++count >= retryCount)
                    {
                        return(false);
                    }
                    await Task.Delay(1);
                }

                return(true);
            }
            catch
            {
                return(false);
            }
        }
        public async Task <bool> TableDeleteAsync(string tableName)
        {
            TableSetting ts             = null;
            bool         enterTableLock = false;

            try
            {
                var db = this.redis.GetDatabase();

                ts = await TableGetSettingAsync(tableName);

                if (null == ts)
                {
                    return(false);
                }

                enterTableLock = await TableLockEnterAsync(ts, "");

                var key = RedisKey.GetRedisKey_TablePrimaryKeyList(tableName);

                // delete every table rows
                var tasklist = new List <Task <bool> >();
                foreach (var primaryKeyValue in db.SetScan(key, "*"))
                {
                    tasklist.Add(TableDeleteRowAsync(tableName, primaryKeyValue.ToString()));
                }

                // delete table schema
                key = RedisKey.GetRedisKey_TableSchema(tableName);
                tasklist.Add(db.KeyDeleteAsync(key));

                // delete table name id
                tasklist.Add(db.HashDeleteAsync(Consts.RedisKey_Hash_TableNameIds, tableName));

                // delete table auto increment column value
                tasklist.Add(db.HashDeleteAsync(Consts.RedisKey_Hash_TableAutoIncrementColumnValues, ts.tableID));

                foreach (var t in tasklist)
                {
                    await t;
                }

                // remove table setting info
                this.tableSettingDic.TryRemove(tableName, out ts);

                return(true);
            }
            catch (Exception ex)
            {
                return(false);
            }
            finally
            {
                if (enterTableLock)
                {
                    await TableLockExit(ts, "");
                }
            }
        }
Example #3
0
        public async Task <bool> TableLockExit(TableSetting tableSetting, string primaryKeyValue)
        {
            try
            {
                var db  = this.redis.GetDatabase();
                var key = RedisKey.GetRedisKey_TableLock(tableSetting.tableName, primaryKeyValue);
                await db.KeyDeleteAsync(key);

                return(true);
            }
            catch
            {
                return(false);
            }
        }
Example #4
0
        private RedisValue[] GetSelectColumnIndexNumbers(TableSetting ts, List <string> selectColumnNames)
        {
            ColumnSetting cs;
            var           len = selectColumnNames.Count;
            var           rva = new RedisValue[len];

            for (var i = 0; i < len; i++)
            {
                if (ts.tableSchemaDic.TryGetValue(selectColumnNames[i], out cs))
                {
                    rva[i] = cs.indexNumber.ToString();
                }
                else
                {
                    // not existing column
                    throw new Exception(string.Format("Table '{0}' does not have '{1}' column", ts.tableName, selectColumnNames[i]));
                }
            }

            return(rva);
        }
Example #5
0
        // wait until enter lock
        public async Task <bool> TableLockEnterAsync(TableSetting tableSetting, string primaryKeyValue)
        {
            try
            {
                var db  = this.redis.GetDatabase();
                var key = RedisKey.GetRedisKey_TableLock(tableSetting.tableName, primaryKeyValue);
                var ts  = new TimeSpan(0, 0, Consts.TableLockExpireSecond);

                var  stw = Stopwatch.StartNew();
                bool ret;
                do
                {
                    ret = await db.StringSetAsync(key, Thread.CurrentThread.ManagedThreadId.ToString(), ts, When.NotExists);

                    if (false == ret)
                    {
                        await Task.Delay(1);
                    }

                    if (stw.ElapsedMilliseconds > Consts.TableLockWaitLongWarningDurationMiliseconds)
                    {
                        // takes too long time to enter table lock: call event handler to notify this situation to user
                        OnEvent(this,
                                new RedisqlEventArgs(RedisqlEventType.Warn,
                                                     string.Format("TableLockEnterAsync takes too long time: TableName={0} PrimaryKeyValue={1}  {2}ms",
                                                                   tableSetting.tableName, primaryKeyValue, stw.ElapsedMilliseconds)));

                        stw.Restart();
                    }
                } while (false == ret);

                return(true);
            }
            catch
            {
                return(false);
            }
        }
        public async Task <bool> TableCreateAsync(string tableName, List <ColumnConfig> columnConfigList, string primaryKeyColumnName)
        {
            TableSetting ts             = null;
            bool         enterTableLock = false;

            try
            {
                var ccflist = new List <ColumnConfig>(columnConfigList);

                // check input parameters
                foreach (var cf in ccflist)
                {
                    if (cf.name.Equals("_id"))
                    {
                        return(false); // _id column name is reserved.
                    }
                    if (cf.makeRankgeIndex)
                    {
                        switch (cf.type.ToString())
                        {
                        case "System.Byte":
                        case "System.Int16":
                        case "System.UInt16":
                        case "System.Int32":
                        case "System.UInt32":
                        case "System.Single":
                        case "System.Double":
                        case "System.DateTime":     // these types could be range indexed
                            break;

                        default:     // other types cannot be range indexed
                            return(false);
                        }
                    }
                }

                // every table automatically generate _id column (auto increment)
                ccflist.Insert(0, new ColumnConfig("_id", typeof(Int64), defaultValue: null));

                ts             = new TableSetting();
                ts.tableName   = tableName;
                enterTableLock = await TableLockEnterAsync(ts, "");

                var db = this.redis.GetDatabase();

                // check table already exists
                var ret = await db.HashExistsAsync(Consts.RedisKey_Hash_TableNameIds, tableName);

                if (ret)
                {
                    return(false); // already existing table name
                }
                // get table id
                var tableID = await db.StringIncrementAsync(Consts.RedisKey_String_TableNameIds);

                // write tableName-id
                await db.HashSetAsync(Consts.RedisKey_Hash_TableNameIds, tableName, tableID);

                // write table schema
                var tableSchemaName = RedisKey.GetRedisKey_TableSchema(tableName);
                int fieldIndex      = 0;
                foreach (var cf in ccflist)
                {
                    bool pkFlag = false;
                    if (cf.defaultValue == null)
                    {
                        cf.defaultValue = "null";
                    }

                    if (cf.name.Equals(primaryKeyColumnName))
                    {
                        pkFlag            = true;
                        cf.makeMatchIndex = false; // primary key column does not need additional match index
                    }

                    var value = string.Format("{0},{1},{2},{3},{4},{5}", (fieldIndex++).ToString(), cf.type.ToString(), cf.makeMatchIndex.ToString(), pkFlag.ToString(), cf.makeRankgeIndex.ToString(), cf.defaultValue.ToString()); // fieldIndex, Type, matchIndexFlag, primaryKeyFlag, rangeIndexFlag, defaultValue
                    await db.HashSetAsync(tableSchemaName, cf.name, value);
                }

                return(true);
            }
            catch (Exception ex)
            {
                return(false);
            }
            finally
            {
                if (enterTableLock)
                {
                    await TableLockExit(ts, "");
                }
            }
        }
        public async Task <bool> TableCreateNewColumnAsync(string tableName, string columnName, Type columnType, bool makeMatchIndex, bool makeRangeIndex, object defaultValue)
        {
            TableSetting ts             = null;
            bool         enterTableLock = false;

            try
            {
                if (defaultValue == null)
                {
                    return(false);
                }

                if (!CheckDataType(columnType, defaultValue.ToString()))
                {
                    return(false);
                }

                var db = this.redis.GetDatabase();

                ts = await TableGetSettingAsync(tableName);

                if (null == ts)
                {
                    return(false);
                }

                enterTableLock = await TableLockEnterAsync(ts, "");

                var cs = new ColumnSetting();
                cs.indexNumber  = ts.GetNextColumnIndexNumber();
                cs.dataType     = columnType;
                cs.isMatchIndex = makeMatchIndex;
                cs.isRangeIndex = makeRangeIndex;
                cs.defaultValue = defaultValue;

                if (cs.dataType == typeof(DateTime))
                {
                    var dvt = defaultValue.ToString().ToLower();
                    if (dvt.Equals("now"))
                    {
                        defaultValue = DateTime.Now.ToString();
                    }
                    else if (dvt.Equals("utcnow"))
                    {
                        defaultValue = DateTime.UtcNow.ToString();
                    }
                }

                ts.tableSchemaDic.Add(columnName, cs);

                if (makeMatchIndex)
                {
                    ts.matchIndexColumnDic.Add(columnName, cs.indexNumber);
                }

                if (makeRangeIndex)
                {
                    ts.rangeIndexColumnDic.Add(columnName, cs.indexNumber);
                }

                ts.columnIndexNameDic.Add(cs.indexNumber.ToString(), columnName);

                var tableSchemaName = RedisKey.GetRedisKey_TableSchema(tableName);

                var value = string.Format("{0},{1},{2},{3},{4},{5}", cs.indexNumber.ToString(), cs.dataType.ToString(), makeMatchIndex.ToString(), "False", makeRangeIndex.ToString(), defaultValue.ToString()); // fieldIndex, Type, IndexFlag, primaryKeyFlag, sortFlag
                await db.HashSetAsync(tableSchemaName, columnName, value);


                var tasklist = new List <Task <bool> >();
                var key      = RedisKey.GetRedisKey_TablePrimaryKeyList(tableName);

                foreach (var primaryKeyValue in db.SetScan(key, "*"))
                {
                    key = RedisKey.GetRedisKey_TableRow(ts.tableID, primaryKeyValue.ToString());
                    tasklist.Add(db.HashSetAsync(key, cs.indexNumber.ToString(), defaultValue.ToString()));

                    if (makeMatchIndex)
                    {
                        // make match index
                        key = RedisKey.GetRedisKey_TableMatchIndexColumn(ts.tableID, cs.indexNumber, defaultValue.ToString());
                        tasklist.Add(db.SetAddAsync(key, primaryKeyValue));
                    }

                    if (makeRangeIndex)
                    {
                        // make range index
                        key = RedisKey.GetRedisKey_TableRangeIndexColumn(ts.tableID, cs.indexNumber);
                        var score = ConvertToScore(cs.dataType, defaultValue.ToString());
                        tasklist.Add(db.SortedSetAddAsync(key, primaryKeyValue, score));
                    }
                }

                foreach (var t in tasklist)
                {
                    if (!await t)
                    {
                        return(false);
                    }
                }

                return(true);
            }
            catch (Exception ex)
            {
                return(false);
            }
            finally
            {
                if (enterTableLock)
                {
                    await TableLockExit(ts, "");
                }
            }
        }
        public async Task <bool> TableDeleteExistingColumnAsync(string tableName, string columnName)
        {
            TableSetting ts             = null;
            bool         enterTableLock = false;

            try
            {
                var db = this.redis.GetDatabase();

                ts = await TableGetSettingAsync(tableName);

                if (null == ts)
                {
                    return(false);
                }

                if (ts.primaryKeyColumnName.Equals(columnName))
                {
                    return(false); // Can not delete PrimaryKey column
                }
                enterTableLock = await TableLockEnterAsync(ts, "");

                ColumnSetting cs;
                if (!ts.tableSchemaDic.TryGetValue(ts.primaryKeyColumnName, out cs))
                {
                    return(false);
                }

                var primaryKeyColumnIndex = cs.indexNumber;

                if (!ts.tableSchemaDic.TryGetValue(columnName, out cs))
                {
                    return(false);
                }

                var tasklist = new List <Task <RedisValue[]> >();
                var key      = RedisKey.GetRedisKey_TablePrimaryKeyList(tableName);

                // read column stored value
                var rva = new RedisValue[2];
                rva[0] = primaryKeyColumnIndex;
                rva[1] = cs.indexNumber;

                foreach (var primaryKeyValue in db.SetScan(key, "*"))
                {
                    key = RedisKey.GetRedisKey_TableRow(ts.tableID, primaryKeyValue.ToString());
                    tasklist.Add(db.HashGetAsync(key, rva));
                }

                var tasklist2 = new List <Task <bool> >();
                foreach (var t in tasklist)
                {
                    var ret = await t;
                    if (cs.isMatchIndex)
                    {
                        key = RedisKey.GetRedisKey_TableMatchIndexColumn(ts.tableID, cs.indexNumber, ret[1].ToString());
                        tasklist2.Add(db.SetRemoveAsync(key, ret[0].ToString()));
                    }

                    if (cs.isRangeIndex)
                    {
                        key = RedisKey.GetRedisKey_TableRangeIndexColumn(ts.tableID, cs.indexNumber);
                        tasklist2.Add(db.SortedSetRemoveAsync(key, ret[0].ToString()));
                    }

                    key = RedisKey.GetRedisKey_TableRow(ts.tableID, ret[0].ToString());
                    tasklist2.Add(db.HashDeleteAsync(key, cs.indexNumber));
                }

                foreach (var t in tasklist2)
                {
                    if (!await t)
                    {
                        return(false);
                    }
                }

                // 데이터를 다 지웠으니 테이블 스키마 제거
                ts.tableSchemaDic.Remove(columnName);
                ts.columnIndexNameDic.Remove(cs.indexNumber.ToString());

                Int32 v;
                if (ts.matchIndexColumnDic.TryGetValue(columnName, out v))
                {
                    ts.matchIndexColumnDic.Remove(columnName);
                }

                if (ts.rangeIndexColumnDic.TryGetValue(columnName, out v))
                {
                    ts.rangeIndexColumnDic.Remove(columnName);
                }

                key = RedisKey.GetRedisKey_TableSchema(tableName);
                await db.HashDeleteAsync(key, columnName);

                return(true);
            }
            catch (Exception ex)
            {
                return(false);
            }
            finally
            {
                if (enterTableLock)
                {
                    await TableLockExit(ts, "");
                }
            }
        }
        // Remove match index to indexed existing table field
        public async Task <bool> TableRemoveMatchIndexAsync(string tableName, string columnName)
        {
            TableSetting ts             = null;
            bool         enterTableLock = false;

            try
            {
                var db = this.redis.GetDatabase();

                ts = await TableGetSettingAsync(tableName);

                if (null == ts)
                {
                    return(false);
                }

                if (ts.primaryKeyColumnName.Equals(columnName))
                {
                    return(false); // Can not remove index to primary key column
                }
                ColumnSetting cs;
                if (!ts.tableSchemaDic.TryGetValue(columnName, out cs))
                {
                    return(false);
                }

                if (!cs.isMatchIndex)
                {
                    return(false); // Not indexed column. Could not remove index.
                }
                enterTableLock = await TableLockEnterAsync(ts, "");

                cs.isMatchIndex = false;
                ts.matchIndexColumnDic.Remove(columnName);

                var tableSchemaName = RedisKey.GetRedisKey_TableSchema(tableName);

                var value = string.Format("{0},{1},{2},{3},{4},{5}", cs.indexNumber.ToString(), cs.dataType.ToString(), cs.isMatchIndex.ToString(), "False", cs.isRangeIndex.ToString(), cs.defaultValue.ToString()); // fieldIndex, Type, IndexFlag, primaryKeyFlag, sortFlag
                await db.HashSetAsync(tableSchemaName, columnName, value);

                //
                var tasklist = new List <Task <bool> >();
                var key      = RedisKey.GetRedisKey_TablePrimaryKeyList(tableName);

                foreach (var primaryKeyValue in db.SetScan(key, "*"))
                {
                    key = RedisKey.GetRedisKey_TableRow(ts.tableID, primaryKeyValue.ToString());
                    var v = await db.HashGetAsync(key, cs.indexNumber);

                    // remove index
                    key = RedisKey.GetRedisKey_TableMatchIndexColumn(ts.tableID, cs.indexNumber, v.ToString());
                    tasklist.Add(db.SetRemoveAsync(key, primaryKeyValue));
                }

                foreach (var t in tasklist)
                {
                    if (!await t)
                    {
                        return(false);
                    }
                }

                return(true);
            }
            catch (Exception ex)
            {
                return(false);
            }
            finally
            {
                if (enterTableLock)
                {
                    await TableLockExit(ts, "");
                }
            }
        }
Example #10
0
        // select one row that matches with primary key column value.
        // If selectColumnNames is null, select all columns in selected row, or select specified columns only.
        public async Task <Dictionary <string, string> > TableSelectRowAsync(List <string> selectColumnNames, string tableName, string primaryKeyColumnValue, bool useTableLock = true)
        {
            TableSetting ts             = null;
            bool         enterTableLock = false;

            try
            {
                var retdic = new Dictionary <string, string>();
                ts = await TableGetSettingAsync(tableName);

                var key = RedisKey.GetRedisKey_TableRow(ts.tableID, primaryKeyColumnValue);
                var db  = this.redis.GetDatabase();

                if (useTableLock)
                {
                    enterTableLock = await TableLockEnterAsync(ts, primaryKeyColumnValue);
                }

                if (null == selectColumnNames)
                {
                    // read all column values
                    var ret = await db.HashGetAllAsync(key);

                    if (null != ret)
                    {
                        var len = ret.Length;
                        for (var i = 0; i < len; i++)
                        {
                            var    e = ret[i];
                            string tableFieldName;
                            if (ts.columnIndexNameDic.TryGetValue(e.Name.ToString(), out tableFieldName))
                            {
                                retdic.Add(tableFieldName, e.Value.ToString());
                            }
                        }
                    }
                }
                else
                {
                    // read specified column values
                    var rva = GetSelectColumnIndexNumbers(ts, selectColumnNames);

                    var ret = await db.HashGetAsync(key, rva);

                    if (null != ret)
                    {
                        for (var i = 0; i < rva.Length; i++)
                        {
                            retdic.Add(selectColumnNames[i], ret[i].ToString());
                        }
                    }
                }

                return(retdic);
            }
            catch
            {
                return(null);
            }
            finally
            {
                if (enterTableLock)
                {
                    await TableLockExit(ts, primaryKeyColumnValue);
                }
            }
        }
Example #11
0
        public async Task <bool> TableDeleteRowAsync(string tableName, string primaryKeyValue, bool useTableLock = true)
        {
            TableSetting ts             = null;
            bool         enterTableLock = false;

            try
            {
                var         db       = this.redis.GetDatabase();
                List <Task> tasklist = new List <Task>();

                ts = await TableGetSettingAsync(tableName);

                if (null == ts)
                {
                    return(false);
                }

                if (useTableLock)
                {
                    enterTableLock = await TableLockEnterAsync(ts, primaryKeyValue);
                }

                // before delete, read all row to delete index
                var key = RedisKey.GetRedisKey_TableRow(ts.tableID, primaryKeyValue);
                var ret = await db.HashGetAllAsync(key);

                if (null == ret)
                {
                    return(false);
                }

                var fvdic = new Dictionary <string, string>();
                foreach (var e in ret)
                {
                    fvdic.Add(e.Name.ToString(), e.Value.ToString());
                }

                // delete match index
                foreach (var fieldIndex in ts.matchIndexColumnDic.Values)
                {
                    key = RedisKey.GetRedisKey_TableMatchIndexColumn(ts.tableID, fieldIndex, fvdic[fieldIndex.ToString()]);
                    tasklist.Add(db.SetRemoveAsync(key, primaryKeyValue));
                }

                // delete range index
                foreach (var e in ts.rangeIndexColumnDic)
                {
                    key = RedisKey.GetRedisKey_TableRangeIndexColumn(ts.tableID, e.Value);
                    tasklist.Add(db.SortedSetRemoveAsync(key, primaryKeyValue));
                }

                // delete table row
                key = RedisKey.GetRedisKey_TableRow(ts.tableID, primaryKeyValue);
                tasklist.Add(db.KeyDeleteAsync(key));

                key = RedisKey.GetRedisKey_TablePrimaryKeyList(tableName);
                tasklist.Add(db.SetRemoveAsync(key, primaryKeyValue));

                foreach (var task in tasklist)
                {
                    await task;
                }

                return(true);
            }
            catch (Exception ex)
            {
                return(false);
            }
            finally
            {
                if (enterTableLock)
                {
                    await TableLockExit(ts, primaryKeyValue);
                }
            }
        }
Example #12
0
        public async Task <bool> TableUpdateRowAsync(string tableName, Dictionary <string, string> updateColumnNameValuePairs, bool useTableLock = true)
        {
            string       key;
            TableSetting ts              = null;
            bool         enterTableLock  = false;
            string       primaryKeyValue = null;

            try
            {
                var         db       = this.redis.GetDatabase();
                List <Task> tasklist = new List <Task>();

                ts = await TableGetSettingAsync(tableName);

                if (null == ts)
                {
                    return(false);
                }

                if (!updateColumnNameValuePairs.TryGetValue(ts.primaryKeyColumnName, out primaryKeyValue))
                {
                    return(false);                                                      // primary key column not found
                }
                var updatedColumns = new Dictionary <string, Tuple <Int32, string> >(); // Column name, Tuple<columnIndex, updatedValue>

                foreach (var e in ts.matchIndexColumnDic)
                {
                    string value;
                    if (updateColumnNameValuePairs.TryGetValue(e.Key, out value))
                    {
                        updatedColumns.Add(e.Key, new Tuple <Int32, string>(e.Value, value)); // update column is index column
                    }
                }

                foreach (var e in ts.rangeIndexColumnDic)
                {
                    string value;
                    if (updateColumnNameValuePairs.TryGetValue(e.Key, out value))
                    {
                        if (!updatedColumns.ContainsKey(e.Key))
                        {
                            updatedColumns.Add(e.Key, new Tuple <Int32, string>(e.Value, value)); // add if not duplicated with index column
                        }
                    }
                }

                if (useTableLock)
                {
                    enterTableLock = await TableLockEnterAsync(ts, primaryKeyValue);
                }

                // get values from stored in update columns
                if (updatedColumns.Count > 0)
                {
                    int index   = 0;
                    var rvArray = new RedisValue[updatedColumns.Count];
                    foreach (var e in updatedColumns)
                    {
                        rvArray[index++] = e.Value.Item1;
                    }

                    key = RedisKey.GetRedisKey_TableRow(ts.tableID, primaryKeyValue);
                    var ret = await db.HashGetAsync(key, rvArray);

                    index = 0;
                    foreach (var e in updatedColumns)
                    {
                        if (ts.matchIndexColumnDic.ContainsKey(e.Key))
                        {
                            // update match index column to new value
                            key = RedisKey.GetRedisKey_TableMatchIndexColumn(ts.tableID, e.Value.Item1, ret[index].ToString());
                            tasklist.Add(db.SetRemoveAsync(key, primaryKeyValue));

                            key = RedisKey.GetRedisKey_TableMatchIndexColumn(ts.tableID, e.Value.Item1, e.Value.Item2);
                            tasklist.Add(db.SetAddAsync(key, primaryKeyValue));
                        }

                        if (ts.rangeIndexColumnDic.ContainsKey(e.Key))
                        {
                            // update range index column to new value
                            key = RedisKey.GetRedisKey_TableRangeIndexColumn(ts.tableID, e.Value.Item1);
                            var score = ConvertToScore(ts.tableSchemaDic[e.Key].dataType, e.Value.Item2);
                            tasklist.Add(db.SortedSetAddAsync(key, primaryKeyValue, score));
                        }

                        index++;
                    }
                }

                int         arrayIndex = 0;
                HashEntry[] heArray    = new HashEntry[updateColumnNameValuePairs.Count];
                foreach (var e in updateColumnNameValuePairs)
                {
                    ColumnSetting cs;
                    if (ts.tableSchemaDic.TryGetValue(e.Key, out cs))
                    {
                        heArray[arrayIndex++] = new HashEntry(cs.indexNumber, e.Value);
                    }
                }

                // save table row
                key = RedisKey.GetRedisKey_TableRow(ts.tableID, primaryKeyValue);
                tasklist.Add(db.HashSetAsync(key, heArray));

                foreach (var task in tasklist)
                {
                    await task;
                }

                return(true);
            }
            catch (Exception ex)
            {
                return(false);
            }
            finally
            {
                if (enterTableLock)
                {
                    await TableLockExit(ts, primaryKeyValue);
                }
            }
        }
Example #13
0
        public async Task <TableSetting> TableGetSettingAsync(string tableName)
        {
            TableSetting ts;
            var          db = this.redis.GetDatabase();

            if (!this.tableSettingDic.TryGetValue(tableName, out ts))
            {
                // 아직 로드되지 않았다. redis로부터 읽어들인다.
                ts           = new TableSetting();
                ts.tableName = tableName;

                // get table id
                var tableID = await db.HashGetAsync(Consts.RedisKey_Hash_TableNameIds, tableName);

                if (RedisValue.Null == tableID)
                {
                    return(null);
                }

                ts.tableID = Convert.ToInt32(tableID.ToString());

                // read table schema
                var tableSchema = await db.HashGetAllAsync(RedisKey.GetRedisKey_TableSchema(tableName));

                if (null == tableSchema)
                {
                    return(null);
                }

                // get table info
                foreach (var e in tableSchema)
                {
                    var tokens = e.Value.ToString().Split(',');

                    var cs = new ColumnSetting();
                    cs.indexNumber = Convert.ToInt32(tokens[0]);

                    switch (tokens[1])
                    {
                    case "System.Byte": cs.dataType = typeof(Byte); break;

                    case "System.Int16": cs.dataType = typeof(Int16); break;

                    case "System.UInt16": cs.dataType = typeof(UInt16); break;

                    case "System.Int32": cs.dataType = typeof(Int32); break;

                    case "System.UInt32": cs.dataType = typeof(UInt32); break;

                    case "System.Int64": cs.dataType = typeof(Int64);  break;

                    case "System.UInt64": cs.dataType = typeof(UInt64); break;

                    case "System.Single": cs.dataType = typeof(Single); break;

                    case "System.Double": cs.dataType = typeof(Double); break;

                    case "System.String": cs.dataType = typeof(String); break;

                    case "System.DateTime": cs.dataType = typeof(DateTime); break;
                    }

                    if (tokens[5].Equals("null"))
                    {
                        cs.defaultValue = null;
                    }
                    else
                    {
                        switch (tokens[1])
                        {
                        case "System.Byte": cs.defaultValue = Convert.ToByte(tokens[5]); break;

                        case "System.Int16": cs.defaultValue = Convert.ToInt16(tokens[5]); break;

                        case "System.UInt16": cs.defaultValue = Convert.ToUInt16(tokens[5]); break;

                        case "System.Int32": cs.defaultValue = Convert.ToInt32(tokens[5]); break;

                        case "System.UInt32": cs.defaultValue = Convert.ToUInt32(tokens[5]); break;

                        case "System.Int64": cs.defaultValue = Convert.ToInt64(tokens[5]); break;

                        case "System.UInt64": cs.defaultValue = Convert.ToUInt64(tokens[5]); break;

                        case "System.Single": cs.defaultValue = Convert.ToSingle(tokens[5]); break;

                        case "System.Double": cs.defaultValue = Convert.ToDouble(tokens[5]); break;

                        case "System.String": cs.defaultValue = Convert.ToString(tokens[5]); break;

                        case "System.DateTime":
                            if (tokens[5].ToLower().Equals("now"))
                            {
                                cs.defaultValue = "now";
                            }
                            else if (tokens[5].ToLower().Equals("utcnow"))
                            {
                                cs.defaultValue = "utcnow";
                            }
                            else
                            {
                                cs.defaultValue = Convert.ToDateTime(tokens[5]);
                            }
                            break;
                        }
                    }

                    cs.isMatchIndex = Convert.ToBoolean(tokens[2]);
                    if (cs.isMatchIndex)
                    {
                        ts.matchIndexColumnDic.Add(e.Name.ToString(), cs.indexNumber);
                    }

                    var fieldPrimaryKeyFlag = Convert.ToBoolean(tokens[3]);
                    if (fieldPrimaryKeyFlag)
                    {
                        ts.primaryKeyColumnName = e.Name;
                    }

                    cs.isRangeIndex = Convert.ToBoolean(tokens[4]);
                    if (cs.isRangeIndex)
                    {
                        ts.rangeIndexColumnDic.Add(e.Name.ToString(), cs.indexNumber);
                    }

                    ts.columnIndexNameDic.Add(cs.indexNumber.ToString(), e.Name.ToString());
                    ts.tableSchemaDic.Add(e.Name.ToString(), cs);
                }

                this.tableSettingDic.TryAdd(tableName, ts);
            }

            return(ts);
        }