The attached test shows that the AbstractBatcher reuses already disposed IDbCommands in some cases (in my case, when an OneToMany entry is inserted and updated in the same commit). This seems to be no problem with some (most?) drivers (I tested SQLite20Driver and OracleClientDriver, both had no problems) but causes an ArgumentOutOfRangeException with the OracleDataClientDriver because the Parameters collection is empty.
The dispose is called from AbstractBatcher.CloseCommand() which is called from OneToManyPersister.DoUpdateRows().
AbstractBatcher.CloseCommand() checks if 'lastQuery' is the just disposed command and if yes clears it, but doesn't check 'batchCommand'. (Possible fix by calling InvalidateBatchCommand() if batchCommand == cmd.)
Seems like a similar problem was already fixed for Firebird because the method AbstractBatcher.PrepareBatchCommand() checks for an empty CommandText and the comment says that it's unknown why it's empty sometimes. (Other possible fix by comparing batchCommand.Parameters.Count and parameterTypes.Length.)
I don't know which of the two fixes would be better (or if there is an even better fix), therefore I didn't create a patch.
Please note that even with one of the two fixes, the test still fails (with an StaleStateException) if you don't set adonet.batch_size to 0. I don't know why it doesn't work with batching, but this seems like a different bug.