将SQL Server数据查询与LUIS意图关联的代码问题求助
修复你的LUIS Bot与SQL Server集成问题
先梳理下代码里的核心问题,这些就是导致无法正常运行的关键:
1. 未实现的方法调用问题
你在ContractualPowerIntent里调用的ContractualPower(context, result)方法直接抛出了NotImplementedException,而且这个方法和另一个同名的ContractualPower(object sender, EventArgs e)是完全独立的两个方法,后者根本没被调用到。
2. SQL查询的严重错误
- 拼接SQL时,错误地把
BeginDate的条件也用了EntityEAN常量,应该是EntityBeginDate - 直接拼接常量字符串
EntityEAN而非从LUIS识别结果中获取实际的实体值,这会导致SQL语法错误 - 直接拼接字符串存在SQL注入风险,必须改用参数化查询
3. Bot环境不适用Console操作
在Azure Web Bot里,Console.WriteLine和Console.ReadLine完全起不到和用户交互的作用,应该通过IDialogContext.PostAsync把查询结果返回给用户。
4. 异步方法的错误定义
数据库操作是异步的,你的方法应该定义为async Task而非void,否则会导致Bot上下文混乱。
修复后的完整代码示例
[Serializable] public class BasicLuisDialog : LuisDialog<object> { public BasicLuisDialog() : base(new LuisService(new LuisModelAttribute( ConfigurationManager.AppSettings["LuisAppId"], ConfigurationManager.AppSettings["LuisAPIKey"], domain: ConfigurationManager.AppSettings["LuisAPIHostName"]))) { } // Constants public const string IntentContractualPower = "SearchContractualPower"; public const string IntentNone = "None"; public const string EntityEAN = "EAN"; public const string EntityBeginDate = "BeginDate"; // 获取识别到的实体字符串 private string BotEntityRecognition(LuisResult result) { StringBuilder entityResults = new StringBuilder(); if (result.Entities.Count > 0) { foreach (EntityRecommendation item in result.Entities) { entityResults.Append($"{item.Type}={item.Entity},"); } // 移除最后一个逗号 if (entityResults.Length > 0) { entityResults.Remove(entityResults.Length - 1, 1); } } return entityResults.ToString(); } [LuisIntent(IntentContractualPower)] public async Task ContractualPowerIntent(IDialogContext context, LuisResult result) { await ProcessContractualPowerQuery(context, result); } private async Task ProcessContractualPowerQuery(IDialogContext context, LuisResult result) { try { // 从LUIS结果中提取实体值 var eanEntity = result.Entities.FirstOrDefault(e => e.Type == EntityEAN); var beginDateEntity = result.Entities.FirstOrDefault(e => e.Type == EntityBeginDate); if (eanEntity == null || beginDateEntity == null) { await context.PostAsync("请提供EAN编号和起始日期,我才能帮你查询合同功率数据。"); context.Wait(MessageReceived); return; } string eanValue = eanEntity.Entity; string beginDateValue = beginDateEntity.Entity; // 使用参数化查询避免SQL注入 SqlConnectionStringBuilder builder = new SqlConnectionStringBuilder(); // 建议从Azure配置中读取连接字符串,而非硬编码 builder.ConnectionString = ConfigurationManager.AppSettings["SqlConnectionString"]; using (SqlConnection connection = new SqlConnection(builder.ConnectionString)) { await connection.OpenAsync(); string sql = @"SELECT ErrorDescription FROM [err].[ErrorFactContractualPower] WHERE EAN = @EAN AND BeginDate = @BeginDate"; using (SqlCommand command = new SqlCommand(sql, connection)) { // 添加参数 command.Parameters.AddWithValue("@EAN", eanValue); command.Parameters.AddWithValue("@BeginDate", beginDateValue); using (SqlDataReader reader = await command.ExecuteReaderAsync()) { if (reader.HasRows) { StringBuilder results = new StringBuilder("查询到的合同功率错误信息:\n"); while (await reader.ReadAsync()) { results.AppendLine(reader.GetString(0)); } await context.PostAsync(results.ToString()); } else { await context.PostAsync("没有找到匹配的合同功率数据。"); } } } } } catch (SqlException ex) { await context.PostAsync($"数据库查询出错:{ex.Message}"); } catch (Exception ex) { await context.PostAsync($"发生未知错误:{ex.Message}"); } context.Wait(MessageReceived); } [LuisIntent(IntentNone)] public async Task NoneIntent(IDialogContext context, LuisResult result) { await ShowLuisResult(context, result); } private async Task ShowLuisResult(IDialogContext context, LuisResult result) { string entities = BotEntityRecognition(result); string roundedScore = result.Intents[0].Score != null ? Math.Round(result.Intents[0].Score.Value, 2).ToString() : "0"; await context.PostAsync($"**查询内容**: {result.Query}, **意图**: {result.Intents[0].Intent}, **置信度**: {roundedScore}. **识别到的实体**: {entities}"); context.Wait(MessageReceived); } }
额外的配置建议
- 连接字符串配置:在Azure Web Bot的应用设置中添加
SqlConnectionString项,把你的SQL Server连接字符串放进去,不要硬编码在代码里,这样更安全且便于维护。 - 实体验证:添加更多的实体格式验证(比如日期格式检查),避免无效的参数传入数据库。
- 错误处理:可以优化错误提示,给用户更友好的指引,而不是直接抛出异常信息。
内容的提问来源于stack exchange,提问作者Adam Richier
相关产品推荐
相关产品推荐

