Inheritance: global::ProtoBuf.IExtensible
    internal static void Load(Msg_LD_Load msg, MyAction<Msg_DL_LoadResult> callback)
    {
        Msg_DL_LoadResult ret = new Msg_DL_LoadResult();
        ret.MsgId = msg.MsgId;
        ret.PrimaryKeys.AddRange(msg.PrimaryKeys);
        ret.SerialNo = msg.SerialNo; ;
        ret.ErrorNo = Msg_DL_LoadResult.ErrorNoEnum.Success;
        if (DataCacheConfig.IsPersistent) {
            try {
                for (int i = 0; i < msg.LoadRequests.Count; ++i) {
                    Msg_LD_SingleLoadRequest req = msg.LoadRequests[i];
                    switch (req.LoadType) {
                        case Msg_LD_SingleLoadRequest.LoadTypeEnum.LoadAll: {
                                int start = req.Start;
                                int count = req.Count;
                                List<GeneralRecordData> datas = DataDML.LoadAll(req.MsgId, start, count);
                                foreach (GeneralRecordData data in datas) {
                                    Msg_DL_SingleRowResult result = new Msg_DL_SingleRowResult();
                                    result.MsgId = req.MsgId;
                                    result.PrimaryKeys.AddRange(data.PrimaryKeys);
                                    result.ForeignKeys.AddRange(data.ForeignKeys);
                                    result.DataVersion = data.DataVersion;
                                    result.Data = data.Data;
                                    ret.Results.Add(result);
                                }
                            }
                            break;
                        case Msg_LD_SingleLoadRequest.LoadTypeEnum.LoadSingle: {
                                GeneralRecordData data = DataDML.LoadSingle(req.MsgId, req.Keys);
                                Msg_DL_SingleRowResult result = new Msg_DL_SingleRowResult();
                                result.MsgId = req.MsgId;

                                if (data != null) {
                                    result.PrimaryKeys.AddRange(data.PrimaryKeys);
                                    result.ForeignKeys.AddRange(data.ForeignKeys);
                                    result.DataVersion = data.DataVersion;
                                    result.Data = data.Data;
                                } else {
                                    result.PrimaryKeys.AddRange(msg.PrimaryKeys);
                                    result.ForeignKeys.Clear();
                                    result.DataVersion = -1;
                                    result.Data = null;
                                    ret.ErrorNo = Msg_DL_LoadResult.ErrorNoEnum.NotFound;
                                }
                                ret.Results.Add(result);
                            }
                            break;
                        case Msg_LD_SingleLoadRequest.LoadTypeEnum.LoadMulti: {
                                List<GeneralRecordData> dataList = DataDML.LoadMulti(req.MsgId, req.Keys);
                                foreach (GeneralRecordData data in dataList) {
                                    Msg_DL_SingleRowResult result = new Msg_DL_SingleRowResult();
                                    result.MsgId = req.MsgId;
                                    result.PrimaryKeys.AddRange(data.PrimaryKeys);
                                    result.ForeignKeys.AddRange(data.ForeignKeys);
                                    result.DataVersion = data.DataVersion;
                                    result.Data = data.Data;
                                    ret.Results.Add(result);
                                }
                            }
                            break;
                    }
                }
            } catch (Exception ex) {
                ret.ErrorNo = Msg_DL_LoadResult.ErrorNoEnum.PostError;
                ret.ErrorInfo = ex.Message;
                LogSys.Log(LOG_TYPE.ERROR, ConsoleColor.Red, "Load data from mysql ERROR. MsgId:{0}, Key:{1}\nErrorMessage:{2}\nStackTrace:{3}",
                              msg.MsgId, msg.PrimaryKeys, ex.Message, ex.StackTrace);
            } finally {
                DataCacheSystem.Instance.QueueAction(callback, ret);
            }
        } else {
            ret.ErrorNo = Msg_DL_LoadResult.ErrorNoEnum.NotFound;
            ret.ErrorInfo = string.Empty;
            DataCacheSystem.Instance.QueueAction(callback, ret);
        }
    }
 private void DSLoadHandler(Msg_LD_Load msg, PBChannel channel, int handle, uint seq)
 {
     try {
         DataCacheSystem.Instance.LoadActionQueue.QueueAction<Msg_LD_Load, PBChannel, int>(DataCacheSystem.Instance.Load, msg, channel, handle);
     } catch (Exception e) {
         var errorReply = new Msg_DL_LoadResult();
         errorReply.MsgId = msg.MsgId;
         errorReply.PrimaryKeys.AddRange(msg.PrimaryKeys);
         errorReply.SerialNo = msg.SerialNo;
         errorReply.ErrorNo = Msg_DL_LoadResult.ErrorNoEnum.Exception;
         errorReply.ErrorInfo = e.Message;
         channel.Send(errorReply);
         LogSys.Log(LOG_TYPE.ERROR, "Load data failed. MsgId:{0}, Key:{1} Error:{2} Detail:{3}", msg.MsgId, msg.PrimaryKeys, e.Message, e.StackTrace);
     }
 }
 //==========================通过QueueAction调用的方法===========================================
 //注意!回调函数目前在缓存线程与db线程都可能调用,回调函数的实现需要是线程安全的(目前一般都是发消息,满足此条件)。
 internal void Load(Msg_LD_Load msg, PBChannel channel, int handle)
 {
     //首先在缓存中查找数据,若未找到,则到DB中查找
     bool isLoadCache = true;
     Msg_DL_LoadResult ret = new Msg_DL_LoadResult();
     ret.MsgId = msg.MsgId;
     ret.PrimaryKeys.AddRange(msg.PrimaryKeys);
     ret.SerialNo = msg.SerialNo;
     ret.ErrorNo = 0;
     for (int i = 0; i < msg.LoadRequests.Count; ++i) {
         Msg_LD_SingleLoadRequest req = msg.LoadRequests[i];
         KeyString loadKey = KeyString.Wrap(req.Keys);
         switch (req.LoadType) {
             case Msg_LD_SingleLoadRequest.LoadTypeEnum.LoadAll: {
                     isLoadCache = false;
                 }
                 break;
             case Msg_LD_SingleLoadRequest.LoadTypeEnum.LoadSingle: {
                     InnerCacheItem item = m_InnerCacheSystem.Find(req.MsgId, loadKey);
                     if (item != null) {
                         Msg_DL_SingleRowResult result = new Msg_DL_SingleRowResult();
                         result.MsgId = req.MsgId;
                         result.PrimaryKeys.AddRange(req.Keys);
                         result.DataVersion = 0;         //TODO: 这个DataVersion有用吗?
                         result.Data = item.DataMessage;
                         ret.Results.Add(result);
                     } else {
                         isLoadCache = false;
                     }
                 }
                 break;
             case Msg_LD_SingleLoadRequest.LoadTypeEnum.LoadMulti: {
                     List<InnerCacheItem> itemList = m_InnerCacheSystem.FindByForeignKey(req.MsgId, loadKey);
                     foreach (var item in itemList) {
                         Msg_DL_SingleRowResult result = new Msg_DL_SingleRowResult();
                         result.MsgId = req.MsgId;
                         result.PrimaryKeys.AddRange(req.Keys);
                         result.DataVersion = 0;         //TODO: 这个DataVersion有用吗?
                         result.Data = item.DataMessage;
                         ret.Results.Add(result);
                     }
                 }
                 break;
         }
     }
     if (isLoadCache) {
         channel.Send(ret);
         LogSys.Log(LOG_TYPE.INFO, "Load data from cache. MsgId:{0}, Key:{1}", msg.MsgId, KeyString.Wrap(msg.PrimaryKeys).ToString());
     } else {
         //查找DB交给DBLoad线程操作
         DbThreadManager.Instance.LoadActionQueue.QueueAction(DataLoadImplement.Load, msg, (MyAction<Msg_DL_LoadResult>)((Msg_DL_LoadResult result) => {
             if (result.ErrorNo == Msg_DL_LoadResult.ErrorNoEnum.Success) {
                 foreach (Msg_DL_SingleRowResult row in result.Results) {
                     m_InnerCacheSystem.AddOrUpdate(row.MsgId, KeyString.Wrap(row.PrimaryKeys), KeyString.Wrap(row.ForeignKeys), row.Data);
                 }
             }
             channel.Send(result);
             LogSys.Log(LOG_TYPE.INFO, "Load data from database. MsgId:{0}, Key:{1}", msg.MsgId, KeyString.Wrap(msg.PrimaryKeys).ToString());
         }));
     }
 }