提问人:Batug Kocak 提问时间:11/8/2023 最后编辑:Batug Kocak 更新时间:11/8/2023 访问量:100
C# LINQ 多行条件
C# LINQ Multiple Line Conditions
问:
public List<VehicleOnTaskDetailDto> GetVehicleOnTaskDetailFinished(VotFilterRequest filterRequest)
{
using VehicleDeliveryContext context = new VehicleDeliveryContext();
var result = (from v in context.VehiclesOnTask
join d in context.Departments on v.DepartmentId equals d.Id
join dr in context.Drivers on v.DriverId equals dr.Id
join vehicle in context.Vehicles on v.VehicleId equals vehicle.Id
where v.IsDeleted != true
where v.IsFinished == true
orderby v.GivenDate descending
select new VehicleOnTaskDetailDto{
VehicleOnTaskId = v.Id,
VehiclePlate = vehicle.Plate,
VehicleId = v.VehicleId,
DriverName = $"{dr.Name} {dr.Surname} - {dr.Mission}",
DepartmentName = d.Name,
TaskDefinition = v.TaskDefinition,
AuthorizedPerson = v.AuthorizedPerson,
Address = v.Address,
GivenDate = v.GivenDate,
ReturnDate = v.ReturnDate
}).ToList();
return result;
}
我想添加 2 行代码取决于 VotFilterRequest 自带的 DateType 过滤器,如下所示:
if (filterRequest.DateType == "GivenDate")
{
where filterRequest.FirstDate <= v.GivenDate
where filterRequest.LastDate >= v.GivenDate
}
else
{
where filterRequest.FirstDate <= v.ReturnDate
where filterRequest.LastDate >= v.ReturnDate
}
我知道你不能这样做,但我也不想重复我的代码。有什么办法可以很快做到这一点吗?谢谢问候。
注意:为了清楚起见,我想使用 LINQ 查询语法,而不是方法语法。
答:
2赞
Michał Turczyn
11/8/2023
#1
通过使用 LINQ 扩展方法并在生成查询期间使用,可以轻松实现它:IQueryable
var query = context.VehiclesOnTask
// You'd need to define those navigation properties.
.Include(x => x.Department)
.Include(x => x.Driver)
.Include(x => x.Vehicle)
.Where(x => x.IsDeleted == false)
.Where(x => x.IsFinished == true);
query = filterRequest.DateType == "GivenDate"
? query.Where(v => filterRequest.FirstDate <= v.GivenDate && filterRequest.LastDate >= v.GivenDate)
: query.Where(v => filterRequest.FirstDate <= v.ReturnDate && filterRequest.LastDate >= v.ReturnDate);
return query
.OrderByDescending(x => x.GivenDate)
.Select(v => new VehicleOnTaskDetailDto
{
VehicleOnTaskId = v.Id,
VehiclePlate = vehicle.Plate,
VehicleId = v.VehicleId,
DriverName = $"{dr.Name} {dr.Surname} - {dr.Mission}",
DepartmentName = d.Name,
TaskDefinition = v.TaskDefinition,
AuthorizedPerson = v.AuthorizedPerson,
Address = v.Address,
GivenDate = v.GivenDate,
ReturnDate = v.ReturnDate,
})
.ToList();
您还可以尝试将筛选器合并到当前查询语法中:
// for better readability we assign condition value to variable:
var isGivenDate = filterRequest.DateType == "GivenDate";
// and incorporate it in the filter.
where (isGivenDate && filterRequest.FirstDate <= v.GivenDate && filterRequest.LastDate >= v.GivenDate)
|| (!isGivenDate && filterRequest.FirstDate <= v.ReturnDate && filterRequest.LastDate >= v.ReturnDate)
评论
0赞
Batug Kocak
11/8/2023
这将起作用,但如果我使用它,我将放弃使用查询语法并将我的函数转换为方法语法。如果可能的话,我正在尝试将其用作查询语法
0赞
Svyatoslav Danyliv
11/8/2023
为什么要添加 Includes?之后,它们被完全忽略了。Select
0赞
Batug Kocak
11/8/2023
他不是通过添加 Includes 来加入表格吗?
2赞
Krzysztof Skowronek
11/8/2023
@BatugKocak 我认为你是真正喜欢查询语法的五个人之一。然后你非常努力地用 C# 编写 SQL,当您可以使用良好的旧 LINQ 方法语法时,将 include 和永远忘记 join。
0赞
Batug Kocak
11/9/2023
我实际上喜欢 SQL 和 C# 以及 LINQ 的新方法,所以这就是为什么我更喜欢查询语法,但如果每个人都使用方法语法,也许我也应该这样做!
1赞
Javad J
11/8/2023
#2
Expression<Func<T, bool>> 可以在 Where() 方法中实例化和使用,您必须在查询之前创建此实例:
Expression<Func<VehicleOnTaskDetailDto, bool>> filter;
if (filterRequest.DateType == "GivenDate") {
filter =
en =>
filterRequest.FirstDate <= en.GivenDate
&& filterRequest.LastDate >= en.GivenDate;
}
else
{
filter =
en =>
filterRequest.FirstDate <= en.ReturnDate
&& filterRequest.LastDate >= en.ReturnDate;
}
并在以下条件中使用此过滤器:
...
.Where(filter)
...
注意: 三元条件也是一个很好的方法,感谢 Michał Turczyn 的回答。
评论
0赞
Batug Kocak
11/8/2023
如果我合并你的两个代码,那会起作用并且实际上看起来不错,但我想使用查询语法。无论如何,感谢您的回答!
1赞
Svyatoslav Danyliv
11/8/2023
#3
您可以使用混合方法,使用它们向记录集添加筛选器。简单来说,使用方法语法更简单:where
public List<VehicleOnTaskDetailDto> GetVehicleOnTaskDetailFinished(VotFilterRequest filterRequest)
{
using var context = new VehicleDeliveryContext();
var vehiclesOnTask = context.VehiclesOnTask.AsQueryable();
if (filterRequest.DateType == "GivenDate")
{
vehiclesOnTask = vehiclesOnTask.Where(v => filterRequest.FirstDate <= v.GivenDate && filterRequest.LastDate >= v.GivenDate)
}
else
{
vehiclesOnTask = vehiclesOnTask.Where(v => filterRequest.FirstDate <= v.ReturnDate && filterRequest.LastDate >= v.ReturnDate)
}
var result = (from v in vehiclesOnTask
join d in context.Departments on v.DepartmentId equals d.Id
join dr in context.Drivers on v.DriverId equals dr.Id
join vehicle in context.Vehicles on v.VehicleId equals vehicle.Id
where v.IsDeleted != true
where v.IsFinished == true
orderby v.GivenDate descending
select new VehicleOnTaskDetailDto{
VehicleOnTaskId = v.Id,
VehiclePlate = vehicle.Plate,
VehicleId = v.VehicleId,
DriverName = $"{dr.Name} {dr.Surname} - {dr.Mission}",
DepartmentName = d.Name,
TaskDefinition = v.TaskDefinition,
AuthorizedPerson = v.AuthorizedPerson,
Address = v.Address,
GivenDate = v.GivenDate,
ReturnDate = v.ReturnDate
}).ToList();
return result;
}
评论
0赞
Batug Kocak
11/8/2023
它会自动将首先 where 方法(在 if-else 语句中)应用于下面的查询吗?
1赞
Svyatoslav Danyliv
11/8/2023
是的,这就是 LINQ 转换器的工作方式。请注意,我已将您的查询更改为使用变量。vehiclesOnTask
评论