【发布时间】:2021-07-04 04:48:59
【问题描述】:
仅当来自前端的参数过滤器为真时,我必须通过 DocumentsUnread > 0 设置过滤器,否则我从查询中返回所有 EmployeeListItem。 DocumentUnread 字段是由其他两个字段相减生成的,它不存在于表 DB 中,而 DocumentCount 是通过 Count 方法生成的。
public async Task<EmployeeList> GetEmployeesDownloadStatus(int pageNumber, string searchText, bool filter)
{
int pageSize = 10;
IQueryable<EmployeeListItem> employees =
from e in context.Employees
join u in context.Users on e.EmployeeId equals u.Employee.EmployeeId
join d in context.EmployeeDocuments on e.EmployeeId equals d.EmployeeId into dj
from d in dj.DefaultIfEmpty()
where
string.IsNullOrWhiteSpace(searchText) ||
(!string.IsNullOrWhiteSpace(searchText) && (e.FirstName).Contains(searchText)) ||
(!string.IsNullOrWhiteSpace(searchText) && (e.LastName).Contains(searchText)) ||
(!string.IsNullOrWhiteSpace(searchText) && (e.FiscalCode).Contains(searchText)) ||
(!string.IsNullOrWhiteSpace(searchText) && (e.IdentificationNumber).Contains(searchText))
group new { e, d, u } by new { e.EmployeeId, e.FirstName, e.LastName, e.FiscalCode, e.IdentificationNumber, e.EmploymentStartDate, u.LastAccessDate } into g
orderby g.Key.FirstName, g.Key.LastName
select new EmployeeListItem
{
EmployeeId = g.Key.EmployeeId,
FirstName = g.Key.FirstName,
LastName = g.Key.LastName,
FiscalCode = g.Key.FiscalCode,
IdentificationNumber = g.Key.IdentificationNumber,
EmploymentStartDate = g.Key.EmploymentStartDate.ToString("dd/MM/yyyy"),
DocumentCount = g.Count(),
DocumentOpened = g.Sum(s => s.d.DownloadedByEmployee ? 1 : 0),
DocumentsUnread = g.Count() - g.Sum(s => s.d.DownloadedByEmployee ? 1 : 0),
LastAccessDate = g.Key.LastAccessDate
};
decimal total = Convert.ToDecimal(employees.Count()) / Convert.ToDecimal(pageSize);
EmployeeList EmployeeList = new BusinessLogic.Dto.EmployeeList
{
TotalPagesNumber = decimal.ToInt32(Math.Ceiling(total)),
Employees = await employees.Skip(pageNumber * pageSize).Take(pageSize).ToListAsync()
};
return EmployeeList;
}
我尝试在 Skip 方法之前使用.Where(item => item.DocumentsUnread > 0).,但出现此错误
The LINQ expression 'DbSet<Employee>()
.Join(
inner: DbSet<User>()
.LeftJoin(
inner: DbSet<Employee>(),
outerKeySelector: u => EF.Property<Nullable<int>>(u, "EmployeeId"),
innerKeySelector: e0 => EF.Property<Nullable<int>>(e0, "EmployeeId"),
resultSelector: (o, i) => new TransparentIdentifier<User, Employee>(
Outer = o,
Inner = i
)),
outerKeySelector: e => e.EmployeeId,
innerKeySelector: u => u.Inner.EmployeeId,
resultSelector: (e, u) => new TransparentIdentifier<Employee, TransparentIdentifier<User, Employee>>(
Outer = e,
Inner = u
))
.LeftJoin(
inner: DbSet<EmployeeDocument>(),
outerKeySelector: ti => ti.Outer.EmployeeId,
innerKeySelector: e1 => e1.EmployeeId,
resultSelector: (ti, e1) => new TransparentIdentifier<TransparentIdentifier<Employee, TransparentIdentifier<User, Employee>>, EmployeeDocument>(
Outer = ti,
Inner = e1
))
.Where(ti0 => False || True && ti0.Outer.Outer.FirstName.Contains(__searchText_0) || True && ti0.Outer.Outer.LastName.Contains(__searchText_0) || True && ti0.Outer.Outer.FiscalCode.Contains(__searchText_0) || True && ti0.Outer.Outer.IdentificationNumber.Contains(__searchText_0))
.GroupBy(
keySelector: ti0 => new {
EmployeeId = ti0.Outer.Outer.EmployeeId,
FirstName = ti0.Outer.Outer.FirstName,
LastName = ti0.Outer.Outer.LastName,
FiscalCode = ti0.Outer.Outer.FiscalCode,
IdentificationNumber = ti0.Outer.Outer.IdentificationNumber,
EmploymentStartDate = ti0.Outer.Outer.EmploymentStartDate,
LastAccessDate = ti0.Outer.Inner.Outer.LastAccessDate
},
elementSelector: ti0 => new {
e = ti0.Outer.Outer,
d = ti0.Inner,
u = ti0.Outer.Inner.Outer
})
.OrderBy(e2 => e2.Key.FirstName)
.ThenBy(e2 => e2.Key.LastName)
.Select(e2 => new EmployeeListItem{
EmployeeId = e2.Key.EmployeeId,
FirstName = e2.Key.FirstName,
LastName = e2.Key.LastName,
FiscalCode = e2.Key.FiscalCode,
IdentificationNumber = e2.Key.IdentificationNumber,
EmploymentStartDate = e2.Key.EmploymentStartDate.ToString("dd/MM/yyyy"),
DocumentCount = e2
.Count(),
DocumentOpened = e2
.Sum(s => s.d.DownloadedByEmployee ? 1 : 0),
DocumentsUnread = e2
.Count() - e2
.Sum(s => s.d.DownloadedByEmployee ? 1 : 0),
LastAccessDate = e2.Key.LastAccessDate
}
)
.Where(e3 => e3.DocumentsUnread > 0)' could not be translated. Either rewrite the query in a form that can be translated, or switch to client evaluation explicitly by inserting a call to 'AsEnumerable', 'AsAsyncEnumerable', 'ToList', or 'ToListAsync'. See https://go.microsoft.com/fwlink/?linkid=2101038 for more information.
我尝试使用 EmployeeList 中的 remove 方法,但这会导致分页出现问题。
我应该翻译成 linq 这个:
having COUNT(*) - COALESCE(SUM(CASE
WHEN [e1].[DownloadedByEmployee] = CAST(1 AS bit) THEN 1
ELSE 0
END), 0)>0
我对其进行了测试并且工作正常,但我不知道如何对 linq 做同样的事情。
感谢您的帮助,我希望我正确地解释了问题
【问题讨论】:
-
您绝对可以在
IQueryable<T>上应用Where扩展方法,检查您的使用部分,可能缺少一些东西。 -
这是实体框架吗?哪个版本?
-
是的,Microsoft.EntityFrameworkCore 版本 5.0.1
-
尝试在投影前加过滤器,可能EF翻译不出来
标签: c# linq iqueryable ef-core-5.0