有没有一种使用查询语法在LINQ查询中执行ToList的整洁方法? [英] Is there a neat way of doing a ToList within a LINQ query using query syntax?
问题描述
考虑以下代码:
StockcheckJobs =
(from job in (from stockcheckItem in MDC.StockcheckItems
where distinctJobs.Contains(stockcheckItem.JobId)
group stockcheckItem by new { stockcheckItem.JobId, stockcheckItem.JobData.EngineerId } into jobs
select jobs).ToList()
let date = MJM.GetOrCreateJobData(job.Key.JobId).CompletedJob.Value
orderby date descending
select new StockcheckJobsModel.StockcheckJob()
{
JobId = job.Key.JobId,
Date = date,
Engineer = (EngineerModel)job.Key.EngineerId,
MatchingLines = job.Count(sti => sti.Quantity == sti.ExpectedQuantity),
DifferingLines = job.Count(sti => sti.Quantity != sti.ExpectedQuantity)
}).ToList()
中间有一个ToList()
,因为GetOrCreateJobData
方法无法转换为sql.
There is a ToList()
in the middle because the GetOrCreateJobData
method can't be translated into sql.
结果,我必须将查询的第一部分括在方括号中,然后再使用外部查询来完成.
As a result I've had to surround the first part of my query in brackets to do this, then I've used an outer query to finish up.
我知道我可以将其分为两个变量,但是我不想这样做(这也在对象初始化程序之内).
I know I could split this into two variables, but I don't want to do that (this is within an object initialiser too).
在我必须执行ToList
(或以其他方式处理linq-to-objects)时,是否可以使用其他语法来提高可读性,最好是不需要外部的内部查询. linq查询的中间?
Is there some other syntax I can use to increase readability, preferably removing the need for an outer an inner query, when I have to do a ToList
(or otherwise get to linq-to-objects) in the middle of a linq query?
在理想的世界中,我想要这样的东西(无论如何都要尽可能近):
In an ideal world I'd like something like this (as close as is possible anyway):
StockcheckJobs =
from stockcheckItem in MDC.StockcheckItems
where distinctJobs.Contains(stockcheckItem.JobId)
group stockcheckItem by new { stockcheckItem.JobId, stockcheckItem.JobData.EngineerId } into jobs
MAGIC_DO_BELOW_AS_LINQ-TO-OBJECTS_KEYWORD_OR_SYNTAX
let date = MJM.GetOrCreateJobData(jobs.Key.JobId).CompletedJob.Value
orderby date descending
select new StockcheckJobsModel.StockcheckJob()
{
JobId = jobs.Key.JobId,
Date = date,
Engineer = new ThreeSixtyScheduling.Models.EngineerModel() { Number = jobs.Key.EngineerId },
MatchingLines = jobs.Count(sti => sti.Quantity == sti.ExpectedQuantity),
DifferingLines = jobs.Count(sti => sti.Quantity != sti.ExpectedQuantity)
};
推荐答案
我要提出两个问题:
- 我真的不认为在此处引入额外的变量不会引起任何可读性问题.实际上,我认为它使"更多"更具可读性,因为它将本地执行"代码与数据库上执行的代码分开了.
- 要简单地切换到LINQ-To-Objects,
AsEnumerable
比ToList
更可取.
- I really don't think there's any readability issue with introducing an extra variable here. In fact, I think it makes it more readable as it separates the "locally executing" code from the code executing on the database.
- To simply switch to LINQ-To-Objects,
AsEnumerable
is preferable toToList
.
也就是说,这就是您如何在整个查询表达式中没有中间AsEnumerable()/ToList()的情况下始终保持在查询状态的方法:通过诱使C#编译器使用您的自定义扩展方法而不是BCL .这是可能的,因为C#使用基于模式"的方法(而不是与BCL耦合)将查询表达式转换为方法调用和lambda.
That said, here's how you can stay in query-land all the way without an intermediate AsEnumerable() / ToList() on the entire query-expression : by tricking the C# compiler into using your custom extension methods rather than the BCL. This is possible since C# uses a "pattern-based" approach (rather than being coupled with the BCL) to turn query-expressions into method-calls and lambdas.
声明这些邪恶的类:
public static class To
{
public sealed class ToList { }
public static readonly ToList List;
// C# should target this method when you use "select To.List"
// inside a query expression.
public static List<T> Select<T>
(this IEnumerable<T> source, Func<T, ToList> projector)
{
return source.ToList();
}
}
public static class As
{
public sealed class AsEnumerable { }
public static readonly AsEnumerable Enumerable;
// C# should target this method when you use "select As.Enumerable"
// inside a query expression.
public static IEnumerable<T> Select<T>
(this IEnumerable<T> source, Func<T, AsEnumerable> projector)
{
return source;
}
}
然后您可以编写如下查询:
And then you can write queries like this:
List<int> list = from num in new[] { 41 }.AsQueryable()
select num + 1 into result
select To.List;
IEnumerable<int> seq = from num in new[] { 41 }.AsQueryable()
select num + 1 into result
select As.Enumerable into seqItem
select seqItem + 1; // Subsequent processing
在您的情况下,您的查询将变为:
In your case, your query would become:
StockcheckJobs =
from stockcheckItem in MDC.StockcheckItems
where distinctJobs.Contains(stockcheckItem.JobId)
group stockcheckItem by new { stockcheckItem.JobId, stockcheckItem.JobData.EngineerId } into jobs
select As.Enumerable into localJobs // MAGIC!
let date = MJM.GetOrCreateJobData(localJobs.Key.JobId).CompletedJob.Value
orderby date descending
select new StockcheckJobsModel.StockcheckJob()
{
JobId = localJobs.Key.JobId,
Date = date,
Engineer = new ThreeSixtyScheduling.Models.EngineerModel() { Number = localJobs.Key.EngineerId },
MatchingLines = localJobs.Count(sti => sti.Quantity == sti.ExpectedQuantity),
DifferingLines = localJobs.Count(sti => sti.Quantity != sti.ExpectedQuantity)
};
不过,我真的不认为这是任何改进.相反,这是对语言功能的严重滥用.
I really don't see this as any sort of improvement, though. Rather, it's pretty heavy abuse of a language feature.
这篇关于有没有一种使用查询语法在LINQ查询中执行ToList的整洁方法?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!