怎樣優雅地增刪查改(九):按日期範圍查詢

2023-07-23 06:00:33

使用資料庫的建立時間作為查詢依據,在Abp框架中,實體類實現ICreationAuditedObject介面,或繼承CreationAuditedEntity類,使用倉儲建立記錄時將自動生成CreationTime。

實現

定義按建立日期範圍查詢(IDateSpanOrientedFilter)介面。

遵守介面隔離原則,將IDateSpanOrientedFilter介面拆分為IStartDateOrientedFilter和IEndDateOrientedFilter介面。

public interface IDateSpanOrientedFilter : IStartDateOrientedFilter, IEndDateOrientedFilter
{

}

按開始日期查詢介面定義如下:

public interface IStartDateOrientedFilter
{
    DateTime? StartDate { get; set; }
}

結束日期介面定義如下:

public interface IEndDateOrientedFilter
{
    DateTime? EndDate { get; set; }
}
  • StartDate:開始日期,記錄的CreationTime 大於等於 該日期的記錄將被篩選
  • EndDate:使用者Id,記錄的CreationTime 小於 該日期的記錄將被篩選

按開始日期查詢

建立應用過濾條件方法:ApplyStartDateOrientedFiltered,在此實現拼接LINQ表示式,程式碼如下:

protected virtual IQueryable<TEntity> ApplyStartDateOrientedFiltered(IQueryable<TEntity> query, TGetListInput input)
{
    if (input is IStartDateOrientedFilter && HasProperty<TEntity>("CreationTime"))
    {
        var property = typeof(TEntity).GetProperty("CreationTime");
        var filteredInput = input as IStartDateOrientedFilter;
        if (filteredInput != null && filteredInput.StartDate.HasValue)
        {
            Expression originalExpression = null;
            var parameter = Expression.Parameter(typeof(TEntity), "p");

            var dateConstantExpression = Expression.Constant(filteredInput.StartDate.Value, typeof(DateTime));

            var propertyAccess = Expression.MakeMemberAccess(parameter, property);
            var expression = Expression.GreaterThanOrEqual(propertyAccess, dateConstantExpression);

            var equalExpression = expression != null ?
                    Expression.Lambda<Func<TEntity, bool>>(expression, parameter)
                    : p => false;


            query = query.Where(equalExpression);

        }

    }
    return query;
}


按結束日期查詢

建立應用過濾條件方法:ApplyEndDateOrientedFiltered,在此實現拼接LINQ表示式,程式碼如下:

protected virtual IQueryable<TEntity> ApplyEndDateOrientedFiltered(IQueryable<TEntity> query, TGetListInput input)
{
    if (input is IEndDateOrientedFilter && HasProperty<TEntity>("CreationTime"))
    {
        var property = typeof(TEntity).GetProperty("CreationTime");
        var filteredInput = input as IEndDateOrientedFilter;
        if (filteredInput != null && filteredInput.EndDate.HasValue)
        {
            Expression originalExpression = null;
            var parameter = Expression.Parameter(typeof(TEntity), "p");

            var dateConstantExpression = Expression.Constant(filteredInput.EndDate.Value, typeof(DateTime));

            var propertyAccess = Expression.MakeMemberAccess(parameter, property);
            var expression = Expression.LessThan(propertyAccess, dateConstantExpression);

            var equalExpression = expression != null ?
                    Expression.Lambda<Func<TEntity, bool>>(expression, parameter)
                    : p => false;


            query = query.Where(equalExpression);

        }

    }
    return query;
}

請注意,可應用過濾的條件為:

  1. input需實現IDateSpanOrientedFilter或子介面;
  2. 實體必須包含「CreationTime」欄位。

否則將原封不動返回IQueryable物件。

使用

無需在應用層中更改程式碼,

在GetAllAlarmInput中實現IDateSpanOrientedFilter介面,程式碼如下:

public class GetAllAlarmInput : PagedAndSortedResultRequestDto, IDateSpanOrientedFilter
{
    public DateTime? StartDate { get; set; }
    public DateTime? EndDate { get; set; }

    ...
}

至此,所有的通用查詢介面已實現完成。在這個專案中,我實現了適合我的聯合查詢方式,你可以根據實際業務需求,擴充套件和調整查詢實現。

專案地址

Github:general-curd-sample