多线程环境中的 PetaPoco 事务

Posted

技术标签:

【中文标题】多线程环境中的 PetaPoco 事务【英文标题】:PetaPoco Transaction in Multithread Env 【发布时间】:2012-06-26 20:40:30 【问题描述】:

我只是以多线程方式测试 PetaPoco Transaction...

我有一个简单的测试用例:

-- 简单的值对象称之为 MediaDevice -- 插入一条记录并更新1000次

void TransactionThread(Object object)



    Database db = (Database) object;

    for(int i= 0; i < 1000;i++)
    


        Transaction transaction = db.GetTransaction();

        MediaDevice device = new  MediaDevice();
        device.Name = "Name";
        device.Brand = "Brand";

        db.Insert(device);

        device.Name = "Name_Updated";
        device.Brand = "Brand_Updated";


        db.Update(device);

        transaction.Complete();

    


    long count = db.ExecuteScalar<long>("SELECT Count(*) FROM MediaDevices");

    Console.WriteLine("Number of all records:" + count);


我在两个线程中这样调用它:[两个线程的单个数据库对象]

void TransactionTest()


    Database db =  GetDatabase();

    Thread tThread1 = ... // thread for  TransactionTest()

    Thread tThread2 = ... // thread for  TransactionTest()

     tThread1.Start(db); // pass Database to TransactionTest()
     tThread2.Start(db); // pass same Database to TransactionTest()


我收到 Null 错误或有时数据库的对象处置错误..

但是当我提供两个数据库实例时,

void TransactionTest()


    Database db =  GetDatabase();
    Database db2 =  GetDatabase();

    Thread tThread1 = ... // thread for  TransactionTest()

    Thread tThread2 = ... // thread for  TransactionTest()


    tThread1.Start(db);  // pass Database instance db to TransactionTest()
    tThread2.Start(db2); // pass Database intance db2 to TransactionTest()


一切正常...

好吧,当我在交易中检查 PetaPoco 源代码时,我在 transaction.Complete 看到了这一点

 public virtual void Complete()
        
            _db.CompleteTransaction();
            _db = null;
        

我的问题是,为了能够使用来自多个线程的事务,我必须使用数据库对象的新副本吗?还是我做错了什么?

为了使其线程安全,我是否必须在每次数据更新查询时打开和关闭新数据库?

【问题讨论】:

【参考方案1】:

您好在选择查询中使用 nolock,因为该表可能已被锁定。 long count = db.ExecuteScalar("SELECT Count(*) with nolock FROM MediaDevices");

【讨论】:

我在这个语句中没有得到异常...db.ExecuteScalar(...)【参考方案2】:

对不起,伙计.. 是的,你是对的。他们将对象更改为空。所以你不能使用同一个对象来线程化。你必须使用他们使用的描述,如 db=GetDataBase() ; db2=GetDataBase();

否则,您可以根据需要更改源代码。我认为他们的许可证允许。但我不确定。

【讨论】:

【参考方案3】:

是的,每个线程都需要一个单独的 PetaPoco 数据库实例。请参阅 PetaPoco 文档中的这句话:

注意:要使事务正常工作,所有操作都需要使用相同的 PetaPoco 数据库对象的实例。所以你可能想要 使用 per-http 请求,或 per-thread IOC 容器来提供 此对象的共享实例。个人 StructureMap 是我的 最喜欢这个。

我将提供线索的短语加粗。也就是说,每个线程都应该使用 PetaPoco 数据库对象的一个​​实例。

【讨论】:

以上是关于多线程环境中的 PetaPoco 事务的主要内容,如果未能解决你的问题,请参考以下文章

Spring在多线程环境下如何确保事务一致性

Spring在多线程环境下如何确保事务一致性

JFinal中的事务开启多线程后是不是有效

多线程中的事务回滚,你真的用对了吗?

在service中启动多线程 怎么控制事务

Spring事务