private async Task LoadDataAsync(string identifier, string conversationId)
        {
            if (string.IsNullOrEmpty(identifier) || string.IsNullOrEmpty(conversationId))
            {
                return;
            }
            Map = await _storage.ReadAsync($"{MAP}:{identifier}", () => _dbContext.KnowledgeMaps.FirstOrDefault(m => m.Identifier == identifier));

            MoMoBotAssert.NotNull(Map);

            Steps = await _storage.ReadAsync($"{MAP}:{identifier}:{STEPS}", () => _dbContext.Steps
                                             .Where(s => s.MapId == Map.Id)
                                             .Select(s => new Step
            {
                Id = s.Id,
                Function = s.Function,
                TriggeredResult = s.TriggeredResult,
                StepType = s.StepType,
                ResultType = s.ResultType,
                Key = s.Key,
                NextStep = s.NextStep,
                PrevStep = s.PrevStep,
                Question = s.Question
            }).ToList());

            var data = await _storage.ReadAsync(GetCacheKey(conversationId, DATA), () => new ConversationData { Next = Steps.FirstOrDefault(s => s.StepType == StepTypes.StartNode)?.Id });

            if (data != null && data.HasNext)
            {
                if (data.Next.Value > 0)
                {
                    Next = Steps.FirstOrDefault(s => s.Id == data.Next.Value)?.Id;
                }
                else if (data.Next.Value == 0)
                {
                    Next = null;
                }
            }
            else
            {
                Next = Steps.FirstOrDefault(s => s.StepType == StepTypes.StartNode)?.Id;
            }
        }
        public async Task <ContinueResult> ContinueAsync(string answer, string conversationId)
        {
            MoMoBotAssert.NotNull(Steps);

            var isQuestion = true;
            var step       = GetCurrentStep();

            if (step != null)
            {
                var result = (string)ExcuteMethod(step.Function, answer);
                // todo : get field's value
                await SetValueAsync(conversationId, step.Key, new FieldItem { Filed = "field", Value = result ?? answer });

                // 分支节点
                if (step.StepType == StepTypes.BranchNode)
                {
                    var next = Steps.FirstOrDefault(s => s.PrevStep == step.Id && s.TriggeredResult == result);
                    if (next != null)
                    {
                        if (next.StepType == StepTypes.RunningNode)
                        {
                            var next2 = Steps.FirstOrDefault(s => s.PrevStep == next.Id);
                            Next       = next2?.Id;
                            isQuestion = !(next2?.StepType == StepTypes.BranchNode);
                        }
                        else
                        {
                            throw new Exception("Error!");
                        }

                        step = next;
                    }
                    else
                    {
                        step = Steps.FirstOrDefault(s => s.StepType == StepTypes.EndNode);
                    }
                }
                // 运行节点与开始节点
                else if (step.StepType == StepTypes.StartNode ||
                         step.StepType == StepTypes.RunningNode)
                {
                    var next = Steps.FirstOrDefault(s => s.Id == step.NextStep);
                    if (next?.StepType == StepTypes.EndNode)
                    {
                        isQuestion = false;
                    }
                    Next = next?.Id;
                }
                // 结束节点
                else
                {
                    Next = 0;//Steps.FirstOrDefault(s => s.StepType == StepTypes.EndNode)?.Id;
                }
            }
            await _storage.WriteAsync(new Dictionary <string, object> {
                { GetCacheKey(conversationId, DATA), new ConversationData {
                      Next = Next ?? 0
                  } }
            });

            return(step == null ? null : new ContinueResult
            {
                IsQuestion = isQuestion,
                Question = step.Question
            });
        }