{"record":{"id":"2115a8f53d4acae2","repo":"tursodatabase/turso","slug":"batch-command-must-be-a-sqlitebatchcommand","errorCode":null,"errorMessage":"Batch command must be a SqliteBatchCommand.","messagePattern":"Batch command must be a SqliteBatchCommand\\.","errorType":"exception","errorClass":"ArgumentException","httpStatus":null,"severity":"error","filePath":"bindings/dotnet/src/Turso.Data.Sqlite/SqliteBatch.cs","lineNumber":569,"sourceCode":"\n    public override void Insert(int index, DbBatchCommand item)\n        => _commands.Insert(index, RequireCommand(item));\n\n    public override bool Remove(DbBatchCommand item)\n        => item is SqliteBatchCommand command && _commands.Remove(command);\n\n    public override void RemoveAt(int index)\n        => _commands.RemoveAt(index);\n\n    protected override DbBatchCommand GetBatchCommand(int index)\n        => _commands[index];\n\n    protected override void SetBatchCommand(int index, DbBatchCommand batchCommand)\n        => _commands[index] = RequireCommand(batchCommand);\n\n    private static SqliteBatchCommand RequireCommand(DbBatchCommand command)\n        => command as SqliteBatchCommand\n           ?? throw new ArgumentException(\n               \"Batch command must be a SqliteBatchCommand.\",\n               nameof(command));\n}\n","sourceCodeStart":551,"sourceCodeEnd":573,"githubUrl":"https://github.com/tursodatabase/turso/blob/6c7252267988c76e632af00a671e4b9788dfae13/bindings/dotnet/src/Turso.Data.Sqlite/SqliteBatch.cs#L551-L573","documentation":"SqliteBatchCommandCollection (Add/Insert/SetBatchCommand) only accepts SqliteBatchCommand instances. Passing any other DbBatchCommand-derived type throws ArgumentException naming the offending parameter, because the collection stores strongly-typed commands that expose managed-statement state.","triggerScenarios":"Calling batch.BatchCommands.Add(someOtherDbBatchCommand) or SetBatchCommand with a command type from another provider (e.g. a custom DbBatchCommand subclass) that is not SqliteBatchCommand.","commonSituations":"Generic ADO.NET code that constructs DbBatchCommand instances and reuses them across providers; refactoring from Microsoft.Data.Sqlite batches while keeping custom command classes.","solutions":["Construct commands with new SqliteBatchCommand() before adding to BatchCommands","Cast or convert generic DbBatchCommand instances to SqliteBatchCommand at the provider boundary","Use 'new' constraint or the concrete SqliteBatch type in helper methods instead of DbBatch"],"exampleFix":"// before\nDbBatchCommand c = new MyBatchCommand(sql);\nbatch.BatchCommands.Add(c); // throws\n// after\nvar c = new SqliteBatchCommand { CommandText = sql };\nbatch.BatchCommands.Add(c);","handlingStrategy":"type-guard","validationCode":"if (command is not SqliteBatchCommand)\n    throw new ArgumentException(\"Expected SqliteBatchCommand.\", nameof(command));","typeGuard":"static bool IsSqliteBatchCommand(DbBatchCommand c) => c is SqliteBatchCommand;","tryCatchPattern":"try { batch.BatchCommands.Add(command); }\ncatch (ArgumentException ex) when (ex.ParamName == \"batchCommand\" || ex.Message.Contains(\"SqliteBatchCommand\"))\n{\n    batch.BatchCommands.Add(new SqliteBatchCommand { CommandText = command.CommandText });\n}","preventionTips":["Always construct batch commands as SqliteBatchCommand, not DbBatchCommand","Type helper methods against SqliteBatch/SqliteBatchCommand instead of the Db* base types","Convert generic command collections at the provider boundary"],"tags":["dotnet","batch","argument"],"backgroundTag":"incompatible-source-type","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"}