Сохраните разговор бота с базой данных Azure sql. Ответ не записывается - PullRequest
0 голосов
/ 04 января 2019

Я создал бота, используя Botframework v3, который записывает диалог в базу данных Azure SQL. Работает с помощью эмулятора бота. Вопросы о том, что бот записан, а ответ пользователя записан в лазурном sql db.

Однако, когда я развернул бота из Visual Studio в Azure, используя канал регистрации бота. (Я развертывал других разных типов ботов много раз, и это обычно работает). Когда я использую бота на (тестовом веб-чате) лазурном портале, он выходит из строя. типы не удается отправить.

Сообщение, которое отправляется / что пользователь набирает делает , записывается в базу данных sql. Однако вопросы, которые задает бот , не записываются в базе данных sql.

Класс SqlActivityogger:

public class SqlActivityLogger : IActivityLogger
    {
    SqlConnection connection;

    public SqlActivityLogger(SqlConnection conn)
    {
        this.connection = conn;
    }
    public async Task LogAsync(IActivity activity)
    {
        string fromId = activity.From.Id;
        string toId = activity.Recipient.Id;
        string message = activity.AsMessageActivity().Text;

        //when creating the sql database make sure you create a table userChatLog table in the db in portal.azure.com
        string insertQuery = "INSERT INTO userChatLog(fromId, toId, message) VALUES (@fromId,@toId,@message)";

        // Passing the fromId, toId, message to the the user chatlog table 
        SqlCommand command = new SqlCommand(insertQuery, connection);
        command.Parameters.AddWithValue("@fromId", fromId);
        command.Parameters.AddWithValue("@toId", toId);
        command.Parameters.AddWithValue("@message", message);



        // Insert to Azure sql database
        command.ExecuteNonQuery();

        //command.ExecuteNonQuery();
        //Debug.WriteLine("Insertion successful of message: " + activity.AsMessageActivity().Text);
    }
}

Global.asax

 public class WebApiApplication : System.Web.HttpApplication
{
    SqlConnection connection = null;
    protected void Application_Start()
    {
        //setting up sql string connection string

        SqlConnectionStringBuilder sqlbuilder = new SqlConnectionStringBuilder();
        sqlbuilder.DataSource = "##########";
        sqlbuilder.UserID = "#####";
        sqlbuilder.Password = "#####";
        sqlbuilder.InitialCatalog = "######";

        connection = new SqlConnection(sqlbuilder.ConnectionString);
        connection.Open();
        Debug.WriteLine("Connection success");


        Conversation.UpdateContainer(builder =>
        {
            builder.RegisterType<SqlActivityLogger>().AsImplementedInterfaces().InstancePerDependency().WithParameter("conn", connection);
        });

        GlobalConfiguration.Configure(WebApiConfig.Register);
    }

    protected void Application_End()
    {

        connection.Close();
        Debug.WriteLine("Connection to database closed");
    }

}

Класс сэндвич

public enum SandwichOptions
{
    BLT, BlackForestHam, BuffaloChicken, ChickenAndBaconRanchMelt, ColdCutCombo, MeatballMarinara,
    OvenRoastedChicken, RoastBeef, RotisserieStyleChicken, SpicyItalian, SteakAndCheese, SweetOnionTeriyaki, Tuna,
    TurkeyBreast, Veggie
};
public enum LengthOptions { SixInch, FootLong };
public enum BreadOptions { NineGrainWheat, NineGrainHoneyOat, Italian, ItalianHerbsAndCheese, Flatbread };
public enum CheeseOptions { American, MontereyCheddar, Pepperjack };
public enum ToppingOptions
{
    Avocado, BananaPeppers, Cucumbers, GreenBellPeppers, Jalapenos,
    Lettuce, Olives, Pickles, RedOnion, Spinach, Tomatoes
};
public enum SauceOptions
{
    ChipotleSouthwest, HoneyMustard, LightMayonnaise, RegularMayonnaise,
    Mustard, Oil, Pepper, Ranch, SweetOnion, Vinegar
};

[Serializable]
public class SandwichOrder
{
    public SandwichOptions? Sandwich;
    public LengthOptions? Length;
    public BreadOptions? Bread;
    public CheeseOptions? Cheese;
    public List<ToppingOptions> Toppings;
    public List<SauceOptions> Sauce;

    public static IForm<SandwichOrder> BuildForm()
    {
        OnCompletionAsyncDelegate<SandwichOrder> processOrder = async (context, state) =>
        {
            await context.PostAsync("This is the end of the form, you would give a final confirmation, and then start the ordering process as needed.");
        };

        return new FormBuilder<SandwichOrder>()
                .Message("Welcome to the simple sandwich order bot!")
                .OnCompletion(processOrder)
                .Build();
    }
};

Ценю помощь. Я уже давно пытаюсь понять это и не понимаю, почему это не работает.

Обновление: После использования ngrok для отладки я получаю следующую ошибку:

{
  "message": "An error has occurred.",
  "exceptionMessage": "String or binary data would be truncated.
The statement has been terminated.",
  "exceptionType": "System.Data.SqlClient.SqlException",
  "stackTrace": "   at System.Data.SqlClient.SqlConnection.OnError(SqlException exception, Boolean breakConnection, Action`1 wrapCloseInAction)
   at System.Data.SqlClient.SqlInternalConnection.OnError(SqlException exception, Boolean breakConnection, Action`1 wrapCloseInAction)
   at System.Data.SqlClient.TdsParser.ThrowExceptionAndWarning(TdsParserStateObject stateObj, Boolean callerHasConnectionLock, Boolean asyncClose)
   at System.Data.SqlClient.TdsParser.TryRun(RunBehavior runBehavior, SqlCommand cmdHandler, SqlDataReader dataStream, BulkCopySimpleResultSet bulkCopyHandler, TdsParserStateObject stateObj, Boolean& dataReady)
   at System.Data.SqlClient.SqlCommand.FinishExecuteReader(SqlDataReader ds, RunBehavior runBehavior, String resetOptionsString, Boolean isInternal, Boolean forDescribeParameterEncryption, Boolean shouldCacheForAlwaysEncrypted)
   at System.Data.SqlClient.SqlCommand.RunExecuteReaderTds(CommandBehavior cmdBehavior, RunBehavior runBehavior, Boolean returnStream, Boolean async, Int32 timeout, Task& task, Boolean asyncWrite, Boolean inRetry, SqlDataReader ds, Boolean describeParameterEncryptionRequest)
   at System.Data.SqlClient.SqlCommand.RunExecuteReader(CommandBehavior cmdBehavior, RunBehavior runBehavior, Boolean returnStream, String method, TaskCompletionSource`1 completion, Int32 timeout, Task& task, Boolean& usedCache, Boolean asyncWrite, Boolean inRetry)
   at System.Data.SqlClient.SqlCommand.InternalExecuteNonQuery(TaskCompletionSource`1 completion, String methodName, Boolean sendToPipe, Int32 timeout, Boolean& usedCache, Boolean asyncWrite, Boolean inRetry)
   at System.Data.SqlClient.SqlCommand.ExecuteNonQuery()
   at FormBot.Models.SqlActivityLogger.<LogAsync>d__2.MoveNext() in C:\\FormSqlTest1-src\\Models\\SqlActivityLogger.cs:line 42
--- End of stack trace from previous location where exception was thrown ---
   at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   at Microsoft.Bot.Builder.Dialogs.Internals.LogPostToBot.<Microsoft-Bot-Builder-Dialogs-Internals-IPostToBot-PostAsync>d__3.MoveNext() in D:\\a\\1\\s\\CSharp\\Library\\Microsoft.Bot.Builder\\ConnectorEx\\IActivityLogger.cs:line 108
--- End of stack trace from previous location where exception was thrown ---
   at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   at Microsoft.Bot.Builder.Dialogs.Conversation.<SendAsync>d__11.MoveNext() in D:\\a\\1\\s\\CSharp\\Library\\Microsoft.Bot.Builder.Autofac\\Dialogs\\Conversation.cs:line 182
--- End of stack trace from previous location where exception was thrown ---
   at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   at Microsoft.Bot.Builder.Dialogs.Conversation.<SendAsync>d__6.MoveNext() in D:\\a\\1\\s\\CSharp\\Library\\Microsoft.Bot.Builder.Autofac\\Dialogs\\Conversation.cs:line 108
--- End of stack trace from previous location where exception was thrown ---
   at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   at System.Runtime.CompilerServices.TaskAwaiter.GetResult()
   at Microsoft.Bot.Sample.FormBot.MessagesController.<Post>d__1.MoveNext() in C:\\FormSqlTest1-src\\Controllers\\MessagesController.cs:line 35
--- End of stack trace from previous location where exception was thrown ---
   at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   at System.Threading.Tasks.TaskHelpersExtensions.<CastToObject>d__3`1.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
   at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   at System.Web.Http.Controllers.ApiControllerActionInvoker.<InvokeActionAsyncCore>d__0.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
   at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   at System.Web.Http.Filters.ActionFilterAttribute.<CallOnActionExecutedAsync>d__5.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
   at System.Web.Http.Filters.ActionFilterAttribute.<CallOnActionExecutedAsync>d__5.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
   at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   at System.Web.Http.Filters.ActionFilterAttribute.<ExecuteActionFilterAsyncCore>d__0.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
   at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   at System.Web.Http.Controllers.ActionFilterResult.<ExecuteAsync>d__2.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
   at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   at System.Web.Http.Dispatcher.HttpControllerDispatcher.<SendAsync>d__1.MoveNext()"
}

Ошибка: «Строковые или двоичные данные будут обрезаны».

Но я просто набираю, например, один привет

Любые предложения ... очень ценю любую помощь здесь. Спасибо

1 Ответ

0 голосов
/ 17 января 2019

Я действительно сталкивался с ошибками усечения SQL раньше, хотя и не при использовании Bot Framework. Очень важно записать максимальную длину столбцов CHAR и VARCHAR, чтобы вы могли убедиться, что все, что записывается в эти столбцы, попадает в пределы. При необходимости вы должны усечь строки самостоятельно перед отправкой их в базу данных.

Как только вы определили максимальную длину ваших столбцов, установите точку останова в вашем методе LogAsync, чтобы вы могли видеть детали каждого действия во время его регистрации. Вы говорите, что печатаете только короткие сообщения типа "привет", но помните, что не ваши сообщения, а сообщения бота не могут войти в систему. Поскольку неясно, какова оперативная разница между сообщениями, которые ваш бот отправляет при запуске в эмуляторе, и другим каналом, обратите внимание также на fromId и toId, особенно если эти столбцы в вашей таблице имеют разную длину. Разные каналы будут генерировать идентификаторы по-разному, и в эмуляторе идентификатор бота обычно состоит из одной цифры.

TL; DR: определите максимальную длину столбцов fromId и toId и message в вашей таблице userChatLog, затем отладьте свой код и посмотрите, как долго будут значения, когда он ломается.

...