[英]C# linq multiple records with different flags to return to a single list
I have multiple records coming back from the DB, and I want to get the price from each row.我从数据库返回了多条记录,我想从每一行中获取价格。 However the price I want to select is dependent from the flags.
但是我想要 select 的价格取决于标志。 I can do the following which brings back the numbers I want, however I would like a cleaner way of doing it.
我可以执行以下操作来返回我想要的数字,但是我想要一种更简洁的方法。
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);
Assuming your Revised
, Original
, NonSentRevised
, NonSentOriginal
are simple types and of the same type.假设您的
Revised
、 Original
、 NonSentRevised
、 NonSentOriginal
是简单类型并且属于同一类型。 You can try the following:您可以尝试以下操作:
var prices = Records.Select(x =>
(x.HasBeenSent ?
(x.Revised != 0 ? x.Revised : x.Original)
: (x.NonSentRevised != 0 ? x.NonSentRevised
: x.NonSentOriginal )))
Note:笔记:
On a second thought we dont need anonymous class as we only need a single property再想想我们不需要匿名 class 因为我们只需要一个属性
As long as the "price" is simple types the code above should work for IQueryable
instances只要“价格”是简单类型,上面的代码就应该适用于
IQueryable
实例
when in doubt, run an SQL profiler to take a peek at the queries being generated如有疑问,请运行 SQL 探查器以查看正在生成的查询
You can try to use Ternary Operator to rewrite as a single query, let your condition in Select
to judgment.你可以尝试使用三元运算符重写为单个查询,让你的条件在
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);
another way, I would write a method to let the code clear另一种方式,我会写一个方法让代码清晰
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;
}
A simple ternary operation should get you what you need.一个简单的三元运算应该可以满足您的需求。
var result =
from x in Records
select
x.HasBeenSent
? (x.Revised != 0 ? x.Revised : x.Original)
: (x.NonSentRevised != 0 ? x.NonSentRevised : x.NonSentOriginal);
With sample data like this使用这样的示例数据
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
I got the following output我得到以下 output
200
500
1200
1500
** Edit ** ** 编辑 **
The SQL code generated by LINQ to SQL is as-expected and efficient 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]
If you are querying against objects (ie, against a IEnumerable<T>
and not against a IQueryable<T>
), you can use pattern matching:如果您正在查询对象(即,针对
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
});
This uses a tuple pattern as a special case of a positional pattern.这使用元组模式作为位置模式的特例。
See also:也可以看看:
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.