有没有一种使用查询语法在LINQ查询中执行ToList的整洁方法? [英] Is there a neat way of doing a ToList within a LINQ query using query syntax?

查看:134
本文介绍了有没有一种使用查询语法在LINQ查询中执行ToList的整洁方法?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

考虑以下代码:

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)
     };

推荐答案

我要提出两个问题:

  1. 我真的不认为在此处引入额外的变量不会引起任何可读性问题.实际上,我认为它使"更多"更具可读性,因为它将本地执行"代码与数据库上执行的代码分开了.
  2. 要简单地切换到LINQ-To-Objects,AsEnumerableToList更可取.
  1. 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.
  2. To simply switch to LINQ-To-Objects, AsEnumerable is preferable to ToList.

也就是说,这就是您如何在整个查询表达式中没有中间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屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆