sqlite只支持1个事务?

时间:2009-11-26 02:34:07

标签: c# .net sqlite concurrency transactions

虽然使用ADO.NET(也许我错了,我不知道它叫什么)我注意到我只能用连接开始一个事务,而命令似乎有命令.Transaction给我的交易数据但不是开始交易本身?实际上看我在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; }

所以SQLite只支持一个交易期?我尝试打开另一个连接,但后来我的事务引发了关于数据库被锁定的异常。所以我不能同时拥有多个连接?

3 个答案:

答案 0 :(得分:4)

每个连接一个事务,是的,但它可以有多个连接(每个连接都有自己的活动事务)。

更新:有趣。我不知道共享缓存模式。如果您的连接使用该模式,则只有一个事务可用于使用相同共享缓存的所有连接。请参阅SQLite shared-cache mode

答案 1 :(得分:1)

我不确定多个连接,它可能与连接锁定文件的事实有关,因为SQLite是基于文件的数据库而不是基于服务器的数据库(在基于服务器的数据库服务器上)保持所有文件锁定并处理并发连接。)

您一次只能打开一个交易。这应该是直观的,因为在您开始交易之后发生的所有事情都在该交易中,直到rollbackcommit。然后你可以开始一个新的。 SQLite要求所有命令都在一个事务中,所以如果你不手动打开一个新命令,它就会为你做。

如果您担心嵌套交易,可以使用savepoint伪造它们。 Documentation

答案 2 :(得分:1)

在1个事务中,您只能读取/写入1个连接,直到事务完成。因此,如果您执行跨越多个sql语句的业务事务,则必须传递连接对象:

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();
            }
        }
    }

连接和transactoin资源由using语句自动释放/关闭。

然后在每个数据提供者方法中执行

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

TransactionScope类是.NET 3.5中的新增功能,如果发生异常,它会自动执行回滚。易于处理......