0

在 Linq 语句的 Where 子句中,像这样,

  var myClasses = (from b in db.MyRecords
                   join p in db.People on b.PersonId equals p.PersonId
                   join cse in db.Courses on b.CourseId equals cse.CourseId
                   where (b.Active == 1)
                   select new { b });

表达式b.Active==1工作正常。但如果我这样做,

Expression<Func<MyRecords, bool>> filter = my => my.Active == 1;

[更新:由于汉斯的回答,我将其保留为原始内容,但实际上,我在这里打错了。表达式实际上使用的是底层类型,而不是像查询 Linq 那样生成的复数形式。我其实有这个

Expression<Func<MyRecord, bool>> filter = my => my.Active == 1;

]

试试这个,

  var myClasses = (from b in db.MyRecords
                   join p in db.People on b.PersonId equals p.PersonId
                   join cse in db.Courses on b.CourseId equals cse.CourseId
                   where (filter)
                   select new { b });

编译器抱怨,

无法将查询表达式转换为预期的委托类型,因为块中的某些返回类型不能隐式转换为委托返回类型

我已经看到很多这样的问题,但我不明白为什么它不起作用。我误解了基本原理,所以我并不是真的要求任何人编写代码。我想知道 Linq 想要什么,所以我对 Linq 有更好的理解,而不仅仅是做一些事情。这有效,例如,

  var myClasses = (from b in db.MyRecords.Where(filter)
                   join p in db.People on b.PersonId equals p.PersonId
                   join cse in db.Courses on b.CourseId equals cse.CourseId
                   select new { b });

我想知道为什么它在那里工作,而不是在加入后的 Where 中。如果我在连接结束时执行 Where,编译器仍然知道 MyRecords 字段,包括 Active。

认为这就是我所追求的正确描述,因为它似乎很适合我的可能。

http://www.albahari.com/nutshell/linqkit.aspx

4

1 回答 1

3

您的过滤器只是在第一个示例中应用的错误类型。蓝色的 linq 语法为您提供了很多神奇的功能,让您可以轻松阅读此查询。幕后实际发生的是创建一些包含对您的项目的引用的匿名类型。请注意,在 where 子句中,您也可以使用pcse变量。当你把它考虑到你的表达式中时,你可能会认为它Expression<Func<Tuple<MyRecords, People, Courses>>实际上是这样的,它不是元组,而是某种匿名类型。

当您要求 resharper 将蓝色语法转换为方法链时,它会像这样生成它:

(db.MyRecords.Join(
     db.People, 
     b => b.PersonId,
     p => p.PersonId,
     (b, p) => new {b, p})
  .Join(
       db.Courses,
       t => t.b.CourseId, 
       cse => cse.CourseId,
       (t, cse) => new {t, cse})
   .Where(t => (t.t.b.Active == 1))
   .Select(t => new {t.t.b}));

实际上,您不能像以前那样在蓝色语法中使用过滤器变量:

... join cse in db.Courses on b.CourseId equals cse.CourseId
               where (filter)

您将不得不切换到方法调用:

(from b in db.MyRecords
                join p in db.People on b.PersonId equals p.PersonId
                join cse in db.Courses on b.CourseId equals cse.CourseId
                select b)
            .Where(filter)

现在只是因为我们将内部查询修剪为b您可以应用过滤器。

于 2018-11-16T15:33:41.477 回答