Answer the question
In order to leave comments, you need to log in
.NET Core and Dapper data access layer?
I am developing a REST API using ASP.NET Core. Data from the API will mainly be received, recording will occur much less frequently.
Getting data should be functional enough: it should be possible to filter, sort data for many fields, get only the required fields, etc. I am using Dapper as ORM.
Previously, I used the repository pattern and the Entity Framework.
My code looked like this:
public class BaseRepository : IDisposable
{
public string ConnectionString { get; set; }
protected BaseRepository()
{
}
protected BaseRepository(string connectionString)
{
ConnectionString = connectionString;
}
protected string GetConnectionStringValue(string connectionStringName) { ... }
}
public abstract class EntityBaseRepository : BaseRepository
{
private DbContext _context;
protected EntityBaseRepository(): base("connectionString")
{
}
protected DbContext Context => _context ?? (_context = CreateEntityContext(GetConnectionStringValue(ConnectionString)));
protected abstract DbContext CreateEntityContext(string connectionString);
protected virtual void SaveEntity<T>(T entity) where T : Entity { ... }
protected virtual void DeleteEntity<T>(T entity) where T : Entity{ ... }
}
public abstract class EntityBaseRepository<TEntity, TSearchOptions, TLoadOptions> : EntityBaseRepository
where TEntity : Entity
where TSearchOptions : SearchOptions
where TLoadOptions : LoadOptions
{
protected IEnumerable<TEntity> GetEntities(TSearchOptions searchOptions, TLoadOptions loadOptions) { ... }
protected async Task<IEnumerable<TEntity>> GetEntitiesAsync(TSearchOptions searchOptions, TLoadOptions loadOptions) { ... }
protected int GetCount(TSearchOptions searchOptions) { ... }
protected TEntity GetEntity(long id, TLoadOptions loadOptions) { ... }
protected virtual IQueryable<TEntity> ApplySearchOptions(DbContext context, IQueryable<TEntity> entities, TSearchOptions searchOptions) { ... }
protected virtual IQueryable<TEntity> ApplyLoadOptions(DbContext context, IQueryable<TEntity> entities, TLoadOptions loadOptions) { ... }
}
public class SearchOptions
{
public List<object> IDs { get; set; }
}
public class SearchOptions<TKey> : SearchOptions
{
public new List<TKey> IDs { get; set; }
}
protected virtual Query ApplySearchOptions(Query query, TSearchOptions searchOptions)
{
if (searchOptions.IDs.Any())
query.WhereIn(FluentMapper.KeyColumnName<TEntity>(), searchOptions.IDs);
return query;
}
Answer the question
In order to leave comments, you need to log in
Why is the choice of Dapper ORM justified ?
If you really need the speed with which the dapper maps, but you are ready to sacrifice the speed of writing code, then do this:
1. Implement SqlBuilder for all needs:
public interface ISqlBuilder
{
SqlBuilder.Template AddTemplate(string sql, dynamic parameters = null);
ISqlBuilder LeftJoin(string sql, dynamic parameters = null);
ISqlBuilder PagingLeftJoin(string sql, dynamic parameters = null);
ISqlBuilder Where(string sql, dynamic parameters = null);
ISqlBuilder PagingWhere(string sql, dynamic parameters = null);
ISqlBuilder OrderBy(string sql, dynamic parameters = null);
ISqlBuilder PagingOrderBy(string sql);
ISqlBuilder Select(string sql, dynamic parameters = null);
ISqlBuilder AddParameters(dynamic parameters);
ISqlBuilder Join(string sql, dynamic parameters = null);
ISqlBuilder GroupBy(string sql, dynamic parameters = null);
ISqlBuilder Having(string sql, dynamic parameters = null);
}
using Dapper;
public class MyEntityQueryBuilder : IQueryBuilder<T>
where T: IEntity
{
private readonly ISqlBuilder _sqlBuilder;
private readonly SqlBuilder.Template _entityTemplate;
private readonly string entity_template = @"
select
/**select**/
from
entity_table e
/**leftjoin**/
/**where**/
/**orderby**/
";
private readonly string split_on = "Id";
public MyEntityQueryBuilder(ISqlBuilder sqlBuilder)
{
_sqlBuilder = sqlBuilder.AddTemplate(entity_template);
}
public Query Build(EntityFilter filter)
{
Select();
LeftJoin();
Where(filter);
Order();
return new Query
{
Sql = _entityTemplate.RawSql,
Parameters = _entityTemplate.Parameters,
SplitOn = split_on,
};
}
private void Select()
{
_builder.Select("e.Id");
_builder.Select("e.Title");
}
private void LeftJoin()
{
_builder.LeftJoin("asn_Responsibles r1 on r1.Id = e.MainResponsibleId");
_builder.LeftJoin("asn_EventResponsibles er on er.EventId = e.Id");
}
private void Where(EntityFilter filter)
{
_builder.Where("e.IsDeleted = 0");
if (filter == null)
{
return;
}
if (filter.Id.HasValue)
{
_builder.Where("e.Id = @id", new { id = filter.Id });
}
if (filter.IsRootOnly)
{
_builder.Where("e.ParentId is null");
}
}
private void Order()
{
_builder.OrderBy("e.CreateDate");
}
}
Didn't find what you were looking for?
Ask your questionAsk a Question
731 491 924 answers to any question