如何将这个lambda表达式转换为linq

时间:2016-08-22 03:53:06

标签: c# linq lambda

我无法阅读复杂的lambda表达式,只能看到超级基本的lambda表达式,我知道我刚开始研究lambda。

正如我上面的标题如何将这个lambda转换为linq?

var train = db.Certificates
            .Join(db.TrainingSchedules, a => a.CertificateId, b => b.CertificateId, (a, b) => new { a, b })
            .Where(x => x.a.Year.Value.Year == year && x.a.TrainingTypeId.Value == trainingTypeId && x.a.IsApproved.Value && x.b.EndDate >= DateTime.Now)
            .Select(z => z.a).Distinct().Where(q => !db.Registrations.Where(s => s.EmployeeId == empId).Select(t => t.Certificate).Any(u => u.CertificateId == q.CertificateId));

有人可以向我解释为什么它有不同的变量吗?喜欢x , q , z , b

3 个答案:

答案 0 :(得分:2)

  

正如我上面的标题如何将这个lambda转换为linq?

你们每个人都在Linq工作过,知道它是怎么样的吗?

如果上面指定的代码不是Linq,那么LinqLambdafluent的{​​{1}}表示的一个组成部分,因为大多数API都需要Linq,这就是Func delegate的用武之地。

  

现在关于Lambda,它们代表什么?

Linq API只是x , q , z , b的扩展方法,如IEnumerable<T>List<T>,我们是否编写Dictionary<TK,TV> Sql fluent' or the Func Delegate {{ 1}} int x,float y,DateTime z`是一种不好的编码方式

关于上面发布的声明,请考虑以下更改:

  • syntax these variables represent, each and every element in the collection, which is processed as part of logic provided by the重命名为, you can certainly use and should use more credible variable to represent the exact thing, similar to other parts of code where,分别指a,bcert,ts个类
  • 不要生成匿名类型Certificate,而是创建一个Training Schedule,如new { a, b },分别包含classCerificateTrainingSchedule类的所有元素,它会在你前进的过程中更容易工作
  • Certificate重命名为Training Schedule,以表示合并x
  • 如果它易于阅读,则在多个链中单独cts子句,例如:

    CerificateTrainingSchedule
  • 同样,可以修改其他变量的名称来表示真正的类及其对象,而不是随机Where。还可以链接调用以清楚地理解逻辑

修改 - //修改了Linq查询

//证书和培训计划的加入/合并版本,根据需要添加更多字段,当前版本基于证书和版本中字段/属性的某些假设。分别是TrainingSchedule课程

.Where(cts => cts.a.Year.Value.Year == year)
.Where(cts => cts.a.TrainingTypeId.Value == trainingTypeId)
.Where(cts => cts.a.IsApproved.Value)
.Where(cts => cts.b.EndDate >= DateTime.Now)

答案 1 :(得分:2)

我认为,根据您的问题,您的意思是希望查询表达式等效于显式调用LINQ方法。如果没有一个好的Minimal, Complete, and Verifiable code example,就不可能确切知道一个正确的例子。但是,以下是我相信你在寻找的东西:

var train =
    from q in
         (from x in
              (from a in db.Certificates
               join b in db.TrainingSchedules on a.CertificateId equals b.CertificateId
               select new { a, b })
          where x.a.Year.Value.Year == year && x.a.TrainingTypeId == trainingTypeId &&
                x.a.IsApproved.Value && x.b.EndDate >= DateTime.Now
          select x.a).Distinct()
     where !(from s in db.Registrations where s.EmployeeId == empId select s.Certificate)
       .Any(u => u.CertificateId == q.CertificateId)
     select q;

请注意,并非所有LINQ方法都具有等效的C#查询表达式语言。特别是,Distinct()Any()没有等价物,所以这些仍然是明确写出来的。

  

有人可以向我解释为什么它有不同的变量吗?像x,q,z,b?

每个lambda表达式的输入位于=>的左侧,结果表达式位于右侧。您所指的变量是输入。这些通常在编写lambda表达式时使用单个字母编写,因为lambda表达式太短,其含义可以清晰,没有更长的变量名。就此而言,独立的lambda表达式甚至可以使用相同的变量名。

请注意,在查询表达式语法中,并非所有变量都“成功”。特别是,我们丢失了zt,因为这些变量是多余的。

在一个表达式中,您可能会发现更长的变量名称有用。但这是一种权衡。查询表达式语言旨在提供一种表示数据源查询的简洁方法。较长的变量名称可能会使查询本身更难理解,即使它可能更容易理解表达式的每个单独部分的意图。这是个人偏好的问题。

答案 2 :(得分:1)

  

我无法阅读复杂的lambda表达式,只能看到超级基本的lambda表达式,我知道我刚开始研究lambda。

试试这个:

var train = db.Certificates
    .Where(c => c.Year.Value.Year == year && 
                c.TrainingTypeId.Value == trainingTypeId &&
                c.IsApproved.Value &&
                c.TrainingSchedules.Any(ts => ts.EndDate >= DateTime.Now) &&
                !c.Registrations.Any(r => r.EmployeeId == empId));

如果可以,那你就没事了。

请注意,这不是示例查询的精确转换,但在功能上是等效的(应该产生相同的结果)。示例查询是编写错误的查询的一个很好的例子 - 变量命名,不必要的乘法Join,这需要一个Distinct运算符(而GroupJoin会做同样的事情而不需要{ {1}}),对两个相似的详细条件(DistinctJoinTrainingSchedulesAny)的处理方式不一致,Registrations部分的标准过于复杂等。

很快,不要写这样的查询。专注于查询所需的结果,并使用最符合逻辑的结构来表达它。如果有导航属性,请避免手动连接。如果您没有导航属性,那么将它们添加到模型中 - 这很容易一次性操作,这在编写查询时会有很大帮助。例如,在我的翻译中,我假设你有类似的东西:

Registrations

更新:以下是使用查询语法的相同内容:

class Certificate
{
    // Other properties ...
    public ICollection<TrainingSchedule> TrainingSchedules { get; set; }  
    public ICollection<Registration> Registrations { get; set; }  
}

class TrainingSchedule
{
    // Other properties ...
    public Certificate Certificate { get; set; }  
}

class Registration
{
    // Other properties ...
    public Certificate Certificate { get; set; }  
}