Question

While using ADO.NET (maybe i am wrong, i dont know what its called) i notice that i can only begin a transaction with a connection and a command seems to have command.Transaction which gets me the transaction data but doesnt start a transaction itself? Actually while looking i see this in System.Data.SQLite

// Summary:
    //     The transaction associated with this command. SQLite only supports one transaction
    //     per connection, so this property forwards to the command's underlying connection.
    [Browsable(false)]
    [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
    public SQLiteTransaction Transaction { get; set; }

So SQLite only supports one transaction period? i tried opening another connection but then my transaction threw an exception about the DB being locked. So i cannot have more then one connection concurrent as well?

Was it helpful?

Solution

One transaction per connection, yes, but it can have more than one connection (each with its own active transaction).

Update: interesting. I didn't know about shared-cache mode. If your connection is using that mode, only one transaction is available for all the connections using the same shared-cache. See SQLite shared-cache mode.

OTHER TIPS

I'm not sure about multiple connections, it probably has to do with the fact that a connection locks the file since SQLite is a file-based DB and not a server-based DB (on a server-based DB the server keeps all of the files locked and deals with concurrent connections).

You can only have one transaction OPEN at a time. This should be make intuitive sense, since everything that happens after you begin a transaction is in that transaction, until either a rollback or commit. Then you can start a new one. SQLite requires all command to be in a transaction, so if you don't manually open a new one, it'll do so for you.

If you're worried about nested transactions, you can fake them with savepoint. Documentation

Within 1 transaction you can only read/write to 1 connection until the transaction is done. Therefore you have to pass the connection object if you do a business transaction that spans several sql statements like this:

public class TimeTableService
    {
        ITimeTableDataProvider _provider = new TimeTableDataProvider();

        public void CreateLessonPlanner(WizardData wizardData)
        {
            using (var con = _provider.GetConnection())
            using (var trans = new TransactionScope())
            {
                con.Open();

                var weekListA = new List<Week>();
                var weekListB = new List<Week>();

                LessonPlannerCreator.CreateLessonPlanner(weekListA, weekListB, wizardData);

                _provider.DeleteLessonPlanner(wizardData.StartDate, con);

                _provider.CreateLessonPlanner(weekListA, con);
                _provider.CreateLessonPlanner(weekListB, con);

                _provider.DeleteTimeTable(TimeTable.WeekType.A, con);
                _provider.StoreTimeTable(wizardData.LessonsWeekA.ToList<TimeTable>(), TimeTable.WeekType.A, con);

                _provider.DeleteTimeTable(TimeTable.WeekType.B, con);
                _provider.StoreTimeTable(wizardData.LessonsWeekB.ToList<TimeTable>(), TimeTable.WeekType.B, con);

                trans.Complete();
            }
        }
    }

The connection and transactoin resources are automatically released/closed by the using-statement.

In every dataprovider method you then do

using(var cmd = new SQLiteCommand("MyStatement",con)
{
   // Create params + ExecuteNonQuery
}

The TransactionScope class is new in .NET 3.5 and is doing automatically a rollback if an exception occurs. Easy handling...

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top