{"record":{"id":"d9f1203c02bcdd94","repo":"tursodatabase/turso","slug":"multi-statement-sqlitecommand-execution-requires-r","errorCode":null,"errorMessage":"Multi-statement SqliteCommand execution requires Read Your Writes=True or an explicit SqliteTransaction on a direct remote connection.","messagePattern":"Multi-statement SqliteCommand execution requires Read Your Writes=True or an explicit SqliteTransaction on a direct remote connection\\.","errorType":"exception","errorClass":"NotSupportedException","httpStatus":null,"severity":"error","filePath":"bindings/dotnet/src/Turso.Data.Sqlite/SqliteCommand.cs","lineNumber":493,"sourceCode":"        }\n    }\n\n    private IReadOnlyList<ManagedSqliteStatement> GetManagedStatements()\n    {\n        var statements = ManagedSqliteStatementParser.Parse(CommandText);\n        if (statements.Any(statement => statement.IsTransactionControl && !CanExecuteSavepointStatement(statement)))\n        {\n            throw new InvalidOperationException(\n                \"Transaction-control SQL is not supported on a managed SqliteConnection. \"\n                + \"Use SqliteConnection.BeginTransaction and SqliteTransaction instead.\");\n        }\n\n        if (statements.Count > 1\n            && Connection!.IsDirectRemote\n            && !Connection.ManagedReadYourWrites\n            && Transaction is null)\n        {\n            throw new NotSupportedException(\n                \"Multi-statement SqliteCommand execution requires Read Your Writes=True \"\n                + \"or an explicit SqliteTransaction on a direct remote connection.\");\n        }\n\n        return statements;\n    }\n\n    private bool CanExecuteSavepointStatement(ManagedSqliteStatement statement)\n    {\n        if (Transaction is null)\n            return false;\n\n        if (statement.FirstKeyword is \"SAVEPOINT\" or \"RELEASE\")\n            return true;\n\n        if (statement.FirstKeyword != \"ROLLBACK\")\n            return false;\n","sourceCodeStart":475,"sourceCodeEnd":511,"githubUrl":"https://github.com/tursodatabase/turso/blob/6c7252267988c76e632af00a671e4b9788dfae13/bindings/dotnet/src/Turso.Data.Sqlite/SqliteCommand.cs#L475-L511","documentation":"This NotSupportedException is thrown by GetManagedStatements when a SqliteCommand with more than one statement is executed over a direct remote TursoConnection that does not manage read-your-writes semantics and is not running inside an explicit SqliteTransaction. Multi-statement execution on a direct remote connection needs either session-level consistency (Read Your Writes=True) or a transaction to guarantee the statements see each other's effects.","triggerScenarios":"Calling ExecuteReader/ExecuteNonQuery/ExecuteScalar on a SqliteCommand whose CommandText contains multiple statements separated by semicolons, while Connection.IsDirectRemote is true, Connection.ManagedReadYourWrites is false, and Command.Transaction is null.","commonSituations":"Developers porting ADO.NET code that runs multi-statement scripts (schema + seed data) against a Turso direct remote database; connection strings built without enabling managed read-your-writes; passing scripts through a command instead of a batch or transaction.","solutions":["Enable Read Your Writes on the connection (set ManagedReadYourWrites/ReadYourWrites=True in the connection options)","Wrap the command execution in an explicit SqliteTransaction (connection.BeginTransaction and assign it to command.Transaction)","Split the multi-statement text into separate SqliteCommand executions","Use a SqliteBatch (supported on direct remote/embedded replica connections) instead of a multi-statement command"],"exampleFix":"// before\nusing var cmd = conn.CreateCommand();\ncmd.CommandText = \"CREATE TABLE t(a); INSERT INTO t VALUES(1);\";\ncmd.ExecuteNonQuery(); // throws on direct remote without RYW\n\n// after\ncmd.CommandText = \"CREATE TABLE t(a); INSERT INTO t VALUES(1);\";\ncmd.Transaction = conn.BeginTransaction();\ncmd.ExecuteNonQuery();\ncmd.Transaction.Commit();","handlingStrategy":"validation","validationCode":"bool safe = conn.IsDirectRemote && !conn.ManagedReadYourWrites\n    ? cmd.CommandText.Count(c => c == ';') <= 1 || cmd.Transaction != null\n    : true;\nif (!safe) throw new InvalidOperationException(\"Split statements, enable Read Your Writes, or use a transaction.\");","typeGuard":"bool CanExecuteMultiStatement(SqliteConnection c, SqliteCommand cmd) =>\n    !c.IsDirectRemote || c.ManagedReadYourWrites || cmd.Transaction is not null;","tryCatchPattern":"try { cmd.ExecuteNonQuery(); }\ncatch (NotSupportedException ex) when (ex.Message.Contains(\"Multi-statement\"))\n{\n    cmd.Transaction = conn.BeginTransaction();\n    cmd.ExecuteNonQuery();\n    cmd.Transaction.Commit();\n}","preventionTips":["Enable Read Your Writes on direct remote connections by default","Prefer SqliteBatch over multi-statement CommandText","Keep schema scripts in separate single-statement commands or run them in a transaction"],"tags":["dotnet","remote-connection","multi-statement","transaction"],"backgroundTag":"unsupported-operation","analyzedSha":"6c7252267988c76e632af00a671e4b9788dfae13","analyzedAt":"2026-09-06T07:15:26.990Z","contentChangedAt":"2026-09-06T07:15:26.990Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}