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

11
假设有两个存储库接口:
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。像那样传递一个开放的事务通常是非常糟糕的设计。(在早期版本中,我自己也犯过这种错误) - Chris Marisic
1个回答

9

我不确定你是否需要仓储+工作单元模式,但我认为在ServiceStack + OrmLite中有一些替代解决方案可以在引入任何模式之前保持代码DRY(特别是如果你主要寻求事务/回滚支持)。我会从类似下面的东西开始。

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,您会将它们放在哪里? - GorillaApe
我猜你可以在发送到DbExec方法的操作/函数中执行尽可能多的特殊/复杂逻辑SQL。也可以编写一个独立的函数并将其(操作/函数)传递到块内。此外,这个例子可能不是处理复杂情况的最佳方法。 - paaschpa

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接