schotime / NPoco

Simple microORM that maps the results of a query onto a POCO object. Project based on Schotime's branch of PetaPoco
Apache License 2.0
847 stars 301 forks source link

Dependency injection example for context #686

Open mchomem opened 1 year ago

mchomem commented 1 year ago

Dependency injection example for context

I'm trying in my test project NPocoTestDrive create a Context class pattern to use with Npoco, using dependency injection.

Does anyone have an example of how to apply it, currently my context class looks like this:

using NPoco;
using NPoco.FluentMappings;
using NPoco.SqlServer;
using NPocoTestDrive.Data.Mappings;
using NPocoTestDrive.Domain.Models;

namespace NPocoTestDrive.Data.Contexts
{
    public class NPocoContext
    {
        public DatabaseFactory? DbFactory { get; set; }

        public Database Get()
        {
            if (DbFactory == null)            
                Setup();

            if (DbFactory == null)
                throw new Exception("DbFactory is null");

            return DbFactory.GetDatabase();
        }

        private void Setup()
        {
            FluentConfig fluentConfig = FluentMappingConfiguration.Configure(new EmployeeMapping());

            DbFactory = DatabaseFactory.Config(x =>
            {
                x.UsingDatabase(() => new SqlServerDatabase(AppSettings.SqlServerConnection));
                x.WithFluentConfig(fluentConfig);
                x.WithMapper(new Mapper());
            });
        }
    }
}

And the repositoy class is:

using NPoco;
using NPocoTestDrive.Data.Contexts;
using NPocoTestDrive.Data.Repositories.Interfaces;
using NPocoTestDrive.Domain.Entities;
using System.Text;

namespace NPocoTestDrive.Data.Repositories
{
    public class EmployeeRepository : IEmployeeRepository
    {
        public async Task Create(Employee entity)
        {
            using (IDatabase db = new NPocoContext().Get())
            {
                await db.InsertAsync(entity);
            }
        }

        public async Task Delete(Employee entity)
        {
            using (IDatabase db = new NPocoContext().Get())
            {
                await db.DeleteAsync(entity);
            }
        }

        public async Task<Employee> Details(Employee? entity = null)
        {
            using (IDatabase db = new NPocoContext().Get())
            {
                return await db.SingleOrDefaultByIdAsync<Employee>(entity.Id);
            }
        }

        public async Task<Employee> DetailsSql(Employee? entity = null)
        {
            throw new NotImplementedException("Method DetailsSql not implemented");
        }

        public async Task<List<Employee>> Retreave(Employee? entity = null)
        {
            using (IDatabase db = new NPocoContext().Get())
            {
                if (entity != null)
                    return await db
                        .Query<Employee>()
                        .Where(x =>
                        (
                             (string.IsNullOrEmpty(entity.Name) || x.Name.Contains(entity.Name))
                             && (string.IsNullOrEmpty(entity.DocumentNumber) || x.DocumentNumber == entity.DocumentNumber)                            
                        ))
                        .ToListAsync();
                else
                    return await db
                        .Query<Employee>()
                        .ToListAsync();
            }
        }

        public async Task<List<Employee>> RetreaveSql(Employee? entity = null)
        {
            using (IDatabase db = new NPocoContext().Get())
            {
                StringBuilder sql = new StringBuilder();
                sql.Append("select");
                sql.Append(" Id");
                sql.Append(" ,Name");
                sql.Append(" ,DocumentNumber");
                sql.Append(" ,Active");
                sql.Append(" ,CreatedIn");
                sql.Append(" ,UpdatedIn");
                sql.Append(" from");
                sql.Append(" Employee");
                sql.Append(" where");
                sql.Append(" (@0 is null or Id = @0)");
                sql.Append(" and (@1 is null or [Name] like '%' + @1 + '%')");
                sql.Append(" and (@2 is null or DocumentNumber = @2)");
                sql.Append(" and (@3 is null or Active = @3)");

                return await db.FetchAsync<Employee>
                    (
                        sql.ToString()
                        , entity?.Id
                        , entity?.Name
                        , entity?.DocumentNumber
                        , entity?.Active
                    );
            }
        }

        public async Task Update(Employee entity)
        {
            using (IDatabase db = new NPocoContext().Get())
            {
                await db.UpdateAsync(entity);
            }
        }
    }
}

And the classes IRepository e IEmployeeRepository:

namespace NPocoTestDrive.Data.Repositories.Interfaces
{
    public interface IRepository<T> where T : class
    {
        Task Create(T entity);
        Task Update(T entity);
        Task Delete(T entity);
        Task<T> Details(T? entity);
        Task<T> DetailsSql(T? entity);
        Task<List<T>> Retreave(T? entity);
        Task<List<T>> RetreaveSql(T? entity);
    }
}
using NPocoTestDrive.Domain.Entities;

namespace NPocoTestDrive.Data.Repositories.Interfaces
{
    public interface IEmployeeRepository: IRepository<Employee>
    {
    }
}

Searching the internet, I found this old point, but it doesn't help much:

https://codereview.stackexchange.com/questions/122010/service-repository-pattern-with-ioc-npoco-micro-orm-and-unit-tests

And I didn't find anything that would help to solve the NPoco project Wiki.

mchomem commented 10 months ago

Hey guys!

I believe I managed to resolve the issue satisfactorily. But if there is a better answer, please be sure to post it here.