怎样优雅地增删查改(九):按日期范围查询

使用数据库的创建时间作为查询依据,在Abp框架中,实体类实现ICreationAuditedObject接口,或继承CreationAuditedEntity类,使用仓储创建记录时将自动生成CreationTime。

实现

定义按创建日期范围查询(IDateSpanOrientedFilter)接口。

遵守接口隔离原则,将IDateSpanOrientedFilter接口拆分为IStartDateOrientedFilter和IEndDateOrientedFilter接口。

1
2
3
4
public interface IDateSpanOrientedFilter : IStartDateOrientedFilter, IEndDateOrientedFilter
{

}

按开始日期查询接口定义如下:

1
2
3
4
public interface IStartDateOrientedFilter
{
DateTime? StartDate { get; set; }
}

结束日期接口定义如下:

1
2
3
4
public interface IEndDateOrientedFilter
{
DateTime? EndDate { get; set; }
}
  • StartDate:开始日期,记录的CreationTime 大于等于 该日期的记录将被筛选
  • EndDate:用户Id,记录的CreationTime 小于 该日期的记录将被筛选

按开始日期查询

创建应用过滤条件方法:ApplyStartDateOrientedFiltered,在此实现拼接LINQ表达式,代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
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表达式,代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
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接口,代码如下:

1
2
3
4
5
6
7
8
public class GetAllAlarmInput : PagedAndSortedResultRequestDto, IDateSpanOrientedFilter
{
public DateTime? StartDate { get; set; }
public DateTime? EndDate { get; set; }

...
}

至此,所有的通用查询接口已实现完成。在这个项目中,我实现了适合我的联合查询方式,你可以根据实际业务需求,扩展和调整查询实现。

项目地址

Github:general-curd-sample

怎样优雅地增删查改(九):按日期范围查询

https://blog.matoapp.net/posts/d178b9a6/

作者

林晓lx

发布于

2023-07-22

更新于

2024-09-11

许可协议

评论