[英]C# linq multiple records with different flags to return to a single list
我从数据库返回了多条记录,我想从每一行中获取价格。 但是我想要 select 的价格取决于标志。 我可以执行以下操作来返回我想要的数字,但是我想要一种更简洁的方法。
var one = Records.Where(x => x.HasBeenSent && x.Revised != 0).Select(x => x.Revised);
var two = Records.Where(x => x.HasBeenSent && x.Revised == 0).Select(x => x.Original);
var three = Records.Where(x => !x.HasBeenSent && x.NonSentRevised != 0).Select(x => x.NonSentRevised);
var four = Records.Where(x => !x.HasBeenSent && x.NonSentRevised == 0).Select(x => x.NonSentOriginal);
假设您的Revised
、 Original
、 NonSentRevised
、 NonSentOriginal
是简单类型并且属于同一类型。 您可以尝试以下操作:
var prices = Records.Select(x =>
(x.HasBeenSent ?
(x.Revised != 0 ? x.Revised : x.Original)
: (x.NonSentRevised != 0 ? x.NonSentRevised
: x.NonSentOriginal )))
笔记:
再想想我们不需要匿名 class 因为我们只需要一个属性
只要“价格”是简单类型,上面的代码就应该适用于IQueryable
实例
如有疑问,请运行 SQL 探查器以查看正在生成的查询
你可以尝试使用三元运算符重写为单个查询,让你的条件在Select
来判断。
var one = Records.Where(x =>
(x.HasBeenSent && x.Revised != 0) ||
(x.HasBeenSent && x.Revised == 0) ||
(x => !x.HasBeenSent && x.NonSentRevised != 0) ||
(!x.HasBeenSent && x.NonSentRevised == 0)
).Select(x => (x.HasBeenSent && x.Revised != 0) ? x.Revised :
(x.HasBeenSent && x.Revised == 0) ? x.Original :
(x => !x.HasBeenSent && x.NonSentRevised != 0) ? x.NonSentRevised:
(!x.HasBeenSent && x.NonSentRevised == 0) x.NonSentOriginal : 0);
另一种方式,我会写一个方法让代码清晰
var one = Records.Where(x =>
(x.HasBeenSent && x.Revised != 0) ||
(x.HasBeenSent && x.Revised == 0) ||
(x => !x.HasBeenSent && x.NonSentRevised != 0) ||
(!x.HasBeenSent && x.NonSentRevised == 0)
).Select(GetPrice);
decimal GetPrice(Record x){
if(HasBeenSent){
if(x.Revised != 0)
return x.Revised;
else
return x.Original;
}
if(!x.HasBeenSent){
if(x.NonSentRevised != 0)
return x.NonSentRevised;
else
return x.NonSentOriginal;
}
return 0;
}
一个简单的三元运算应该可以满足您的需求。
var result =
from x in Records
select
x.HasBeenSent
? (x.Revised != 0 ? x.Revised : x.Original)
: (x.NonSentRevised != 0 ? x.NonSentRevised : x.NonSentOriginal);
使用这样的示例数据
HasBeenSent Original Revised NonSentOriginal NonSentRevised
1 100 200 300 400 200
1 500 0 700 800 500
0 900 1000 1100 1200 1200
0 1300 1400 1500 0 1500
我得到以下 output
200
500
1200
1500
** 编辑 **
LINQ到SQL生成的SQL代码符合预期,高效
-- Region Parameters
DECLARE @p0 Int = 0
DECLARE @p1 Int = 0
-- EndRegion
SELECT
(CASE
WHEN [x].[HasBeenSent] = 1 THEN
(CASE
WHEN [x].[Revised] <> @p0 THEN [x].[Revised]
ELSE [x].[Original]
END)
WHEN [x].[NonSentRevised] <> @p1 THEN [x].[NonSentRevised]
ELSE [x].[NonSentOriginal]
END) AS [value]
FROM [Records] AS [x]
如果您正在查询对象(即,针对IEnumerable<T>
而不是针对IQueryable<T>
),您可以使用模式匹配:
var result = Records
.Select(x => (x.HasBeenSent, x.Revised, x.NonSentRevised) switch {
(true, not 0, _) => x.Revised,
(true, 0, _) => x.Original,
(false, _, not 0) => x.NonSentRevised,
(false, _, 0) => x.NonSentOriginal
});
这使用元组模式作为位置模式的特例。
也可以看看:
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.