Article Directory
accomplish
Define the query by user (IUserOrientedFilter) interface
public interface IUserOrientedFilter
{
public string EntityUserIdIdiom { get; }
Guid? UserId { get; set; }
}
- EntityUserIdIdiom: Semantic UserId, used to specify the name used to describe the "UserId" field in the business entity, if not specified, the default is "UserId"
- UserId: User Id, if it is Guid.Empty, use the Id of the currently logged in user
If the query entity list Dto implements this interface, it will filter the associated entities under the specified UserId.
If the specified UserId is Guid.Empty, the UserId of the currently logged-in user will be used.
ICurrentUser is a service of Abp, which is used to obtain the information of the currently logged in user
Create the method of applying filter conditions: ApplyUserOrientedFiltered, here realize splicing LINQ expressions, the code is as follows:
protected virtual IQueryable<TEntity> ApplyUserOrientedFiltered(IQueryable<TEntity> query, TGetListInput input)
{
if (input is IUserOrientedFilter)
{
var filteredInput = input as IUserOrientedFilter;
var entityUserIdIdiom = filteredInput.EntityUserIdIdiom;
if (string.IsNullOrEmpty(entityUserIdIdiom))
{
entityUserIdIdiom = "UserId";
}
if (HasProperty<TEntity>(entityUserIdIdiom))
{
var property = typeof(TEntity).GetProperty(entityUserIdIdiom);
if (filteredInput != null && filteredInput.UserId.HasValue)
{
Guid userId = default;
if (filteredInput.UserId.Value == Guid.Empty)
{
using (var scope = ServiceProvider.CreateScope())
{
var currentUser = scope.ServiceProvider.GetRequiredService<ICurrentUser>();
if (currentUser != null)
{
userId = currentUser.GetId();
}
}
}
else
{
userId = filteredInput.UserId.Value;
}
var parameter = Expression.Parameter(typeof(TEntity), "p");
var keyConstantExpression = Expression.Constant(userId, typeof(Guid));
var propertyAccess = Expression.MakeMemberAccess(parameter, property);
var expression = Expression.Equal(propertyAccess, keyConstantExpression);
var equalExpression = expression != null ?
Expression.Lambda<Func<TEntity, bool>>(expression, parameter)
: p => false;
query = query.Where(equalExpression);
}
}
}
return query;
}
Note that the conditions under which filtering can be applied are:
- The input needs to implement the IUserOrientedFilter interface;
- Entities must be associated with users.
Otherwise, the IQueryable object will be returned unchanged.
use
No need to change code in the application layer,
Implement the IUserOrientedFilter interface in GetAllAlarmInput, the code is as follows:
public class GetAllAlarmInput : PagedAndSortedResultRequestDto, IUserOrientedFilter
{
Guid? UserId { get; set; }
public string EntityUserIdIdiom { get; }
// 或显式实现
// public string EntityUserIdIdiom => "UserId";
...
}
test
Create some organizational structures, named "Groups"
Create some customers (Client) under different "groups"
In the alarm management page, create some alarms and assign these alarms to different customers
After the alarm is created, enter the customer management, click "View Details" in the customer list on the right
Open the customer details page, click the "Alarm" tab, you can see the alarm list under the customer