henkmollema / Dommel

CRUD operations with Dapper made simple.
MIT License
611 stars 99 forks source link

Functions that may help #299

Closed fernandocristan closed 2 months ago

fernandocristan commented 8 months ago

I implemented this function in my base repository and this helps me a lot by making searches easier. I believe that From-queries helps too, it's even better i believe, but I'm just leaving it here because maybe it can help someone.

Function that returns entity few properties base on a predicate.

Returns a list

public virtual async Task<List<TEntity>> SelectAsync(
      Func<TEntity, object> properties,
      Expression<Func<TEntity, bool>> predicate)
  {
      if (properties == null)
      {
          throw new ArgumentNullException(nameof(properties));
      }

      // Invoke the selector expression to obtain an object instance of anonymous type
      object obj = properties.Invoke(NewEntityFunc());
      PropertyInfo[] paramProps = obj.GetType().GetProperties();

      List<PropertyInfo> selectedProps = new();
      PropertyInfo[] entityProps = typeof(TEntity).GetProperties();
      selectedProps.AddRange(from paramProp in paramProps
                             from entityProp in entityProps
                             where entityProp.Name == paramProp.Name
                             select entityProp);
      IEnumerable<string> columns = selectedProps.Select(p => Resolvers.Column(p, _conn));
      string tableName = Resolvers.Table(typeof(TEntity), _conn);
      string querySql = $"select {string.Join(", ", columns)} from {tableName}";

      DynamicParameters queryParameters = new();
      if (predicate != null)
      {
          SqlExpression<TEntity> sqlexp = new(DommelMapper.GetSqlBuilder(_conn));
          querySql += " " + sqlexp.Where(predicate).ToSql(out queryParameters);
      }
      IEnumerable<TEntity> data = await _conn.QueryAsync<TEntity>(querySql, queryParameters, _transaction);
      return data.ToList();
  }

Returns single object

public virtual async Task<TEntity> SelectFirstAsync(
    Func<TEntity, object> properties,
    Expression<Func<TEntity, bool>> predicate)
{
    List<TEntity> data = await SelectAsync(properties, predicate);
    if (data.Any())
    {
        return data.First();
    }

    return null;
}

Usage

List

List<MovementItem> orderItems = await repository.SelectAsync(
    x => new
    {
        x.Id,
        x.Description,
        x.Quantity,
        x.UnitaryValue,
        x.Subtotal
    },
    x => x.MovementId == order.Id);

Single object

Settings parameters = await repository.SelectFirstAsync(
    x => new
    {
        x.DefaultSaleAccountPlanId,
        x.DefaultCostCenterId
    },
    x => x.Id == user.BranchCompanyId);
henkmollema commented 2 months ago

Thanks, but I will close this issue now.