数据存储缓存数据条目类型 Protobuf对象对应数据库表中的一行数据
        private Dictionary<KeyString, KeyString> m_PrimaryForeignDict = new Dictionary<KeyString, KeyString>(); //primaryKey-foreignKey

        #endregion Fields

        #region Methods

        /// <summary>
        /// 添加或更新
        /// </summary>
        /// <param name="key">主键,不能为空</param>
        /// <param name="foreignKey">外键,可以为空</param>
        /// <param name="dataMessage">数据值</param>
        /// <param name="dataVersion">数据版本</param>
        internal void AddOrUpdate(KeyString key, KeyString foreignKey, byte[] dataMessage, long cacheVersion)
        {
            InnerCacheItem cacheItem = null;
            m_PrimaryDict.TryGetValue(key, out cacheItem);
            if (cacheItem == null) {
                //数据不在缓存中
                if (dataMessage == null) {
                    //被删除的数据
                    return;
                }
                cacheItem = new InnerCacheItem(dataMessage);
                m_PrimaryDict.Add(key, cacheItem);
                if (!KeyString.IsNullOrEmpty(foreignKey)) {
                    m_PrimaryForeignDict[foreignKey] = key;
                    HashSet<KeyString> associateKeys = null;
                    m_ForeignPrimaryDict.TryGetValue(foreignKey, out associateKeys);
                    if (associateKeys != null) {
                        associateKeys.Add(key);
                    } else {
                        associateKeys = new HashSet<KeyString>();
                        associateKeys.Add(key);
                        m_ForeignPrimaryDict.Add(foreignKey, associateKeys);
                    }
                }
            } else {
                //数据已在缓存中
                if (CompareDataVersion(cacheVersion, cacheItem.CacheVersion)) {
                    //更新缓存
                    cacheItem.DirtyState = DirtyState.Unsaved;
                    cacheItem.Valid = true;
                    cacheItem.CacheVersion = cacheVersion;
                    if (dataMessage == null) {
                        cacheItem.Valid = false;
                    } else {
                        cacheItem.DataMessage = dataMessage;
                    }
                    //更新外键关系
                    if (!KeyString.IsNullOrEmpty(foreignKey)) {
                        m_PrimaryForeignDict[foreignKey] = key;
                        HashSet<KeyString> associateKeys = null;
                        m_ForeignPrimaryDict.TryGetValue(foreignKey, out associateKeys);
                        if (associateKeys != null) {
                            associateKeys.Add(key);
                        } else {
                            associateKeys = new HashSet<KeyString>();
                            associateKeys.Add(key);
                            m_ForeignPrimaryDict.Add(foreignKey, associateKeys);
                        }
                    }
                } else {
                    //新数据的dataVersion低,不更新缓存,输出警告日志
                    LogSys.Log(LOG_TYPE.WARN, "Update cache version WARN. Key:{0}, NewCacheVersion:{1}, OldCacheVersion:{2}", key, cacheVersion, cacheItem.CacheVersion);
                }
            }
        }
 //向DB中写入一条数据
 internal static int SingleSaveItem(int msgId, InnerCacheItem cacheItem, int dataVersion)
 {
     if (DataCacheConfig.IsPersistent) {
         try {
             DataDML.Save(msgId, cacheItem.Valid, dataVersion, cacheItem.DataMessage);
         } catch (Exception ex) {
             DBConn.Close();
             LogSys.Log(LOG_TYPE.ERROR, "SingleSaveItem ERROR. MsgId:{0}, Error:{1}\nStacktrace:{2}", msgId, ex.Message, ex.StackTrace);
             throw ex;
         }
     }
     return 1;
 }
        /// <summary>
        /// 主键查询
        /// </summary>
        /// <param name="key">主键</param>
        /// <returns>若查找到返回唯一对应数据值,否则返回null</returns>
        internal InnerCacheItem Find(KeyString key)
        {
            InnerCacheItem cacheItem = null;

            m_PrimaryDict.TryGetValue(key, out cacheItem);
            if (cacheItem != null && cacheItem.Valid)
            {
                return(cacheItem);
            }
            else
            {
                return(null);
            }
        }
        /// <summary>
        /// 外键查询
        /// </summary>
        /// <param name="foreignKey">外键</param>
        /// <returns>外键所对应的数据值列表</returns>
        internal List <InnerCacheItem> FindByForeignKey(KeyString foreignKey)
        {
            List <InnerCacheItem> cacheItemList = new List <InnerCacheItem>();
            HashSet <KeyString>   associateKeys = null;

            m_ForeignPrimaryDict.TryGetValue(foreignKey, out associateKeys);
            if (associateKeys != null)
            {
                foreach (var key in associateKeys)
                {
                    InnerCacheItem cacheItem = this.Find(key);
                    if (cacheItem != null && cacheItem.Valid)
                    {
                        cacheItemList.Add(cacheItem);
                    }
                }
            }
            return(cacheItemList);
        }
 //在DBThread线程中执行
 private void SaveDirtyItemToDB(int msgId, InnerCacheItem cacheItem, string saveCountKey, int saveCount, int dbDataVersion)
 {
     try {
         DataSaveImplement.SingleSaveItem(msgId, cacheItem, dbDataVersion);
         //写入DB成功
         DataCacheSystem.Instance.QueueAction(() => {
             cacheItem.DirtyState = DirtyState.Saved;
         });
     } catch (Exception e) {
         //写入DB失败
         DataCacheSystem.Instance.QueueAction(() => {
             cacheItem.DirtyState = DirtyState.Unsaved;
         });
         LogSys.Log(LOG_TYPE.ERROR, "Save to MySQL ERROR:{0}, \nStacktrace:{1}", e.Message, e.StackTrace);
     }
 }
        /// <summary>
        /// 添加或更新
        /// </summary>
        /// <param name="key">主键,不能为空</param>
        /// <param name="foreignKey">外键,可以为空</param>
        /// <param name="dataMessage">数据值</param>
        /// <param name="dataVersion">数据版本</param>
        internal void AddOrUpdate(KeyString key, KeyString foreignKey, byte[] dataMessage, long cacheVersion)
        {
            InnerCacheItem cacheItem = null;

            m_PrimaryDict.TryGetValue(key, out cacheItem);
            if (cacheItem == null)
            {
                //数据不在缓存中
                if (dataMessage == null)
                {
                    //被删除的数据
                    return;
                }
                cacheItem = new InnerCacheItem(dataMessage);
                m_PrimaryDict.Add(key, cacheItem);
                if (!KeyString.IsNullOrEmpty(foreignKey))
                {
                    m_PrimaryForeignDict[foreignKey] = key;
                    HashSet <KeyString> associateKeys = null;
                    m_ForeignPrimaryDict.TryGetValue(foreignKey, out associateKeys);
                    if (associateKeys != null)
                    {
                        associateKeys.Add(key);
                    }
                    else
                    {
                        associateKeys = new HashSet <KeyString>();
                        associateKeys.Add(key);
                        m_ForeignPrimaryDict.Add(foreignKey, associateKeys);
                    }
                }
            }
            else
            {
                //数据已在缓存中
                if (CompareDataVersion(cacheVersion, cacheItem.CacheVersion))
                {
                    //更新缓存
                    cacheItem.DirtyState   = DirtyState.Unsaved;
                    cacheItem.Valid        = true;
                    cacheItem.CacheVersion = cacheVersion;
                    if (dataMessage == null)
                    {
                        cacheItem.Valid = false;
                    }
                    else
                    {
                        cacheItem.DataMessage = dataMessage;
                    }
                    //更新外键关系
                    if (!KeyString.IsNullOrEmpty(foreignKey))
                    {
                        m_PrimaryForeignDict[foreignKey] = key;
                        HashSet <KeyString> associateKeys = null;
                        m_ForeignPrimaryDict.TryGetValue(foreignKey, out associateKeys);
                        if (associateKeys != null)
                        {
                            associateKeys.Add(key);
                        }
                        else
                        {
                            associateKeys = new HashSet <KeyString>();
                            associateKeys.Add(key);
                            m_ForeignPrimaryDict.Add(foreignKey, associateKeys);
                        }
                    }
                }
                else
                {
                    //新数据的dataVersion低,不更新缓存,输出警告日志
                    LogSys.Log(LOG_TYPE.WARN, "Update cache version WARN. Key:{0}, NewCacheVersion:{1}, OldCacheVersion:{2}", key, cacheVersion, cacheItem.CacheVersion);
                }
            }
        }