我正在尝试使用实体框架过滤我的GET方法...如果条件有效,请使用
public async Task<List<TimeEntryViewModel>> Get(TimeEntryFilter filter)
{
var result = await _readRepository
.FindByCondition(x => x.IsApproved == true)
.Include(x => x.Task)
.Include(x => x.Account)
.Select(x => new TimeEntryViewModel
{
AccountName = x.Account.Name,
Date = x.Date,
StartTime = x.StartTime,
FinishTime = x.FinishTime,
InternalId = x.InternalId,
TaskId = x.TaskId,
TaskName = x.Task.Name,
CreatedBy = x.CreatedBy,
CustomerName = x.Task.Project.ServiceOrder.Customer.Name
}).ToListAsync().ConfigureAwait(false);
if (filter.AccountName != null ||
(filter.StartDate.HasValue && filter.FinishDate.HasValue && (filter.StartDate <= filter.FinishDate)) ||
(filter.TaskName != null) ||
(filter.CustomerName != null) ||
(filter.InternalId != null))
result = result.Where(x =>
(x.AccountName.ToString().Contains(filter.AccountName)) &&
(x.Date >= filter.StartDate && x.Date <= filter.FinishDate) &&
(x.CustomerName.ToString().Contains(filter.CustomerName)) &&
(x.TaskName.ToString().Contains(filter.TaskName)) &&
(x.InternalId.ToString().Contains(filter.InternalId.ToString()))).ToList();
return result;
}
但是我想有一种无需使用if就能改进此方法的方法
我已经尝试过这样做(只显示过滤器帐户名) 但返回内部服务器错误
var result = await _readRepository
.FindByCondition(x => x.IsApproved == true)
.Where(x => string.IsNullOrEmpty(filter.AccountName) || x.Account.Name.ToString().Contains(filter.AccountName))
.Include(x => x.Task)
.Include(x => x.Account)
.Select(x => new TimeEntryViewModel
{
Id = x.Id,
AccountName = x.Account.Name,
Date = x.Date,
Description = x.Description,
StartTime = x.StartTime,
FinishTime = x.FinishTime,
InternalId = x.InternalId,
OnSite = x.OnSite,
IsApproved = x.IsApproved,
IsBillable = x.IsBillable,
TaskId = x.TaskId,
TaskName = x.Task.Name,
CreatedBy = x.CreatedBy,
CustomerName = x.Task.Project.ServiceOrder.Customer.Name
}).ToListAsync().ConfigureAwait(false);
好的,伙计们EDIT1:在我的第二个示例中,使用InternalId代替Account.Name
.Where(x => (string.IsNullOrEmpty(filter.InternalId.ToString())) || x.InternalId.ToString().Contains(filter.InternalId.ToString()))
它起作用了。...我认为我在处理表中的外键问题时遇到了麻烦...
答案 0 :(得分:1)
有一种非常有趣的方法,可将多个布尔值(包含或不包含等)仅包含一个值。这称为按位操作。此处:Most common C# bitwise operations on enums 您可以找到使用这种“技术”的不同方法。
答案 1 :(得分:1)
它返回null,因为您不检查Account
属性是否为null。
AccountName = x.Account.Name
因此,以上内容将引发Null引用异常。
避免这种情况的一种方法是使用null conditional operator:
AccountName = x.Account?.Name
对于以下属性,您也可以采用相同的方法:
Task.Name
Task.Project.ServiceOrder.Customer.Name
并使用相同的运算符安全地访问它们,如下所示:
Task?.Name
Task?.Project?.ServiceOrder?.Customer?.Name
基于上述内容,您可以按照已经对AccountName
属性进行操作的方式进行操作,但是同时也可以使用空条件运算符。
答案 2 :(得分:1)
您似乎需要&&
运算符:
.Where(x => string.IsNullOrEmpty(filter?.AccountName)
&& x?.Account?.Name.ToString().Contains(filter.AccountName))
因为使用||
运算符,所以可以在NullReferenceException
的表达式的第二部分中获得Where
:
x?.Account?.Name.ToString().Contains(filter.AccountName))
答案 3 :(得分:0)
我认为使用if
是添加过滤器的一种非常清晰的方法。但是,您应该将result
设为IQueryable
,而不是具体化您希望在sql服务器上执行过滤器的查询。
因此删除.ToListAsync().ConfigureAwait(false);
var result = await _readRepository...
if(...)
return result.Where(x => ...).ToListAsync().ConfigureAwait(false);
return result.ToListAsync().ConfigureAwait(false);
答案 4 :(得分:0)
好吧,显然,我的问题是x.Account.Name之后的Auth::user()
我不能使用ToString()...我不知道为什么,但是现在没有if条件就可以工作
Auth::hasUser()
如果有人知道它为什么起作用,我会很感激