Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

ServiceStack + ORMLite + Repository Pattern

I'm trying to implement the Repository pattern using ORMLite. I initially started off with:

public List<Todo> GetByIds(long[] ids)
{
    using (IDbConnection dbConn = dbFactory.OpenDbConnection())
    {
        return dbConn.Ids<Todo>(ids).ToList();
    }
}

But having this under every method in my Repository seemed a bit repetitive? So I created a data context class which all my repositories inherit from:

public class TodoRepository : DataContext

Here is that DataContext class:

public class DataContext
{
    protected OrmLiteConnectionFactory dbFactory = new 
OrmLiteConnectionFactory(ConfigurationManager.ConnectionStrings["AppDb"].
ConnectionString, SqlServerOrmLiteDialectProvider.Instance);

    protected IDbConnection dbConn;

    public DataContext()
    {
        dbConn = dbFactory.OpenDbConnection();
    }
}

I then simply have to do this in my methods:

public List<Todo> GetByIds(long[] ids)
{
    return dbConn.Ids<Todo>(ids).ToList();
}

I was just curious if this is a good design pattern and what other's have come up with when using the Repository pattern for data access with ORMLite.

like image 699
CallumVass Avatar asked Jan 23 '13 12:01

CallumVass


2 Answers

I wouldn't hard-code the strong-type DialectProvider and configuration for the connection in your repository. Instead I would do something that's similar to ServiceStack's base Service class, e.g:

public class Repository : IDisposable {

    public IDbConnectionFactory DbFactory { get; set; } //injected by IOC

    IDbConnection db;
    IDbConnection Db 
    { 
        get 
        {
            return db ?? db = DbFactory.Open();
        }
    }

    public List<Todo> GetByIds(long[] ids)
    {
        return Db.Ids<Todo>(ids);
    }

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

This way you can initialize the IDbConnectionFactory where it's meant to be, i.e. in the IOC registration of your Host project. In ServiceStack this is in AppHost.Configure():

container.Register<IDbConnectionFactory>(c => 
    OrmLiteConnectionFactory(ConfigurationManager.ConnectionStrings["AppDb"].
        ConnectionString, SqlServerDialect.Provider);

container.RegisterAutoWired<Repository>().ReusedWithin(ReuseScope.None); 
like image 63
mythz Avatar answered Nov 02 '22 00:11

mythz


I know this is an old question but I thought I'd chip in. My services access a IGenericRepository<T> that access a IDatabaseContext (could be anything that uses System.Data.IDbConnection, but in this case ServiceStack's OrmLite), which in turn uses ServiceStack's IDbConnectionFactory:

public class GenericRepository<T> : IGenericRepository<T>
    where T : class
{
    private readonly IDatabaseContext _databaseContext;

    public GenericRepository(IDatabaseContext databaseContext)
    {
        _databaseContext = databaseContext;
    }

    public T Get(int id)
    {
        return _databaseContext.Query(db =>
            {
                return db.SingleById<T>(id);
            });
    }

    public async Task<T> GetAsync(int id)
    {
        return await _databaseContext.QueryAsync(async db =>
        {
            return await db.SingleByIdAsync<T>(id);
        });
    }

    // other methods (All, First, etc)
}

IDbConnectionFactory is registered as

container.Register<IDbConnectionFactory>(c => 
    OrmLiteConnectionFactory(ConfigurationManager.ConnectionStrings["AppDb"].
        ConnectionString, SqlServerDialect.Provider);

The IDatabaseContext for OrmLite:

public class OrmLiteDatabaseContext : IDatabaseContext
{
    private readonly IDbConnectionFactory _dbConnectionFactory;

    public DatabaseContext(IDbConnectionFactory dbConnectionFactory)
    {
        _dbConnectionFactory = dbConnectionFactory;
    }

    public T Query<T>(Func<IDbConnection, T> query)
    {
        using (var connection = _dbConnectionFactory.OpenDbConnection())
        {
            return query(connection);
        }
    }

    public async Task<T> QueryAsync<T>(Func<IDbConnection, Task<T>> query)
    {
        using (var connection = _dbConnectionFactory.OpenDbConnection())
        {
            return await query(connection);
        }
    }
}

which works pretty well.

like image 34
eth0 Avatar answered Nov 02 '22 00:11

eth0