使用 ServiceStack.ORMLite 的存储库模式中的事务

Posted

技术标签:

【中文标题】使用 ServiceStack.ORMLite 的存储库模式中的事务【英文标题】:Transactions in the Repository Pattern using ServiceStack.ORMLite 【发布时间】:2013-02-04 23:27:15 【问题描述】:

我正在使用 ServiceStack.ORMLite 实现存储库模式,如下所示:

public class MyRepository : IMyRepository

    private IDbConnectionFactory DbConnectionFactory = null;

    public MyRepository(IDbConnectionFactory dbConnectionFactory)
    
        DbConnectionFactory = dbConnectionFactory;
    

    public void MyMethod()
    
        using (var connection = DbConnectionFactory.OpenDbConnection())
        using (var cmd = connection.CreateCommand())
        
            //Do something here
        
    

但是当我需要在 DbTransaction 中扭曲一些 DB 操作时,我不知道如何处理 DbTransaction。看起来TransactionScope 是一个解决方案,但我不知道这是否过于繁重。

【问题讨论】:

【参考方案1】:

ServiceStack OrmLite 让您可以访问 ADO.NET 的原始 IDbConnectionIDbTransaction 类,您应该使用它们来代替 TransactionScope 的。您可以使用IDbConnection.OpenTransaction()扩展方法创建事务,例如:

public class MyRepository : IMyRepository, IDisposable

    private IDbConnectionFactory DbFactory  get; set; 

    private IDbConnection db;
    private IDbConnection Db
    
        get  return db ?? (db = dbFactory.Open()); 
    

    public void WithTransactions()
    
        using (var trans = Db.OpenTransaction())
        
            //Do something here

            trans.Commit();
        
    

    public List<Poco> WithoutTransactions()
    
        return Db.Select<Poco>();
    

    public void Dispose()
    
        if (db != null) 
            db.Dispose();
    

由于它需要更少的代码,我更喜欢属性注入并使用 Lazy Db 属性来简化我的方法的数据访问模式。

注意:每当您的任何类保留对打开的 IDbConnection 的引用(例如这个)时,它都应该使用 None/TransientRequestScope 进行注册因此连接在使用后被释放(即不要将其注册为单例)。

【讨论】:

每个请求只打开一次 IDbConnection 并在使用后处理好?我认为我应该在每个方法开始时打开连接并在方法结束时关闭它。 没关系,如果您使用连接池(即 SqlServer 的默认行为),连接并没有真正关闭,它只是释放回池中。但是,无论哪种方式都可以使用 Request Scope,因为它是每个请求的单线程,因此可以安全地与同一请求范围内的其他依赖项共享连接实例。 如果一个请求长时间保持连接,但它只需要访问DB只是一个monent(比如为DB选择一些数据然后处理它),我认为DB的性能会不好...但是手动处理连接并不容易... 你没有正当理由这么想。如果长时间运行的连接需要多次访问数据库,你会怎么做?在同一个请求中多次重新打开数据库连接?打开新连接比重新使用现有连接更好吗?看来你不了解连接池或者多线程,不要想太多,答案是使用 Transient 或者 RequestScope。但是,如果您是偏执狂,请随时像您在示例中所做的那样,每次都明确地打开和关闭连接。 我想我可能误解了 IDbTransaction IDbCommand 和 IDbConnection 之间的关系...我同意你的说法...【参考方案2】:

我喜欢 mythz 的回答,但根据 mythz 的反馈,我自己在让事情按预期工作时遇到了一些麻烦。我遇到了另一个答案,起初,它似乎不是我想要的,但最终让我朝着正确的方向前进。

Best practices of implementing unit of work and repository pattern using ServiceStack.ORMLite

【讨论】:

以上是关于使用 ServiceStack.ORMLite 的存储库模式中的事务的主要内容,如果未能解决你的问题,请参考以下文章

在 SQL Server 和 ServiceStack.OrmLite 中使用架构名称

ServiceStack.OrmLite 调用存储过程

使用 ServiceStack.ORMLite 实现工作单元和存储库模式的最佳实践

软删除使用servicestack.ormlite问题,怎么解决

在运行时在 ServiceStack.OrmLite 中获取类的表名/避免硬编码表名

ServiceStack.OrmLite 入门