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

Posted

技术标签:

【中文标题】使用 ServiceStack.ORMLite 实现工作单元和存储库模式的最佳实践【英文标题】:Best practices of implementing unit of work and repository pattern using ServiceStack.ORMLite 【发布时间】:2013-02-05 02:06:53 【问题描述】:

假设有两个repository接口:

interface IFooRepository

    void Delete(int id);


interface IBarRepository

    void Delete(int id);

还有一个 IUnitOfWork 接口,例如:

interface IUnitOfWork : IDisposable

    void Commit();
    void Rollback();

使用 ServiceStack.ORMLite 实现这些接口的最佳实践是什么,以便用户可以像使用它们一样

MyFooRepository.Delete(4);
// if an Exception throws here, Bar won't be deleted
MyBarRepository.Delete(7);

或者

using (var uow = CreateUnitOfWork())

    MyFooRepository.Delete(4);
    MyBarRepository.Delete(7);
    uow.Commit();  //now they are in an transaction

【问题讨论】:

我建议尽可能避免使用 UOW。像这样传递一个开放的交易通常是一个非常糟糕的设计。 (在早期的修订中,我自己也犯了这件事) 【参考方案1】:

不确定您是否需要 Repository + UnitOfWork 模式,但我认为 ServiceStack + OrmLite 中有一些替代解决方案可以在您需要引入任何模式之前保持您的代码“干燥”(特别是如果您主要寻求事务/回滚支持)。下面是我要开始的地方。

public class Foo //POCO for data access

    //Add Attributes for Ormlite
    public int Id  get; set;  


public class Bar //POCO for data access

    //Add Attributes for Ormlite
    public int Id  get; set; 


//your request class which is passed to your service
public class DeleteById 

    public int Id  get; set; 


public class FooBarService : MyServiceBase //MyServiceBase has resusable method for handling transactions. 

    public object Post(DeleteById request)
    
        DbExec(dbConn =>
                   
                       dbConn.DeleteById<Foo>(request.Id);
                       dbConn.DeleteById<Bar>(request.Id);
                   );

        return null;
    


public class MyServiceBase : Service

    public IDbConnectionFactory DbFactory  get; set; 

    protected void DbExec(Action<IDbConnection> actions)
    
        using (var dbConn = DbFactory.OpenDbConnection())
        
            using (var trans = dbConn.OpenTransaction())
            
                try
                
                    actions(dbConn);
                    trans.Commit();
                
                catch (Exception ex)
                
                    trans.Rollback();
                    throw ex;
                
            
        
    
 

一些参考资料...

https://github.com/ServiceStack/ServiceStack.RedisWebServices - 上面的代码是根据这个例子修改的

https://groups.google.com/forum/#!msg/servicestack/1pA41E33QII/R-trWwzYgjEJ - 讨论 ServiceStack 中的层

http://ayende.com/blog/3955/repository-is-the-new-singleton - Ayende Rahien(NHibernate 核心贡献者)关于存储库模式

【讨论】:

如果您需要特殊/复杂的逻辑 sql,您会将它们放在哪里? 我想您可以在发送到 DbExec 方法的操作/函数中执行任意多的特殊/复杂逻辑 sql。也可以编写一个独立的函数并在块中传递它(动作/函数)。此外,此示例可能不是复杂情况的最佳方法。

以上是关于使用 ServiceStack.ORMLite 实现工作单元和存储库模式的最佳实践的主要内容,如果未能解决你的问题,请参考以下文章

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

ServiceStack.OrmLite 调用存储过程

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

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

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

ServiceStack.OrmLite 入门