为什么在where扩展方法中使用lambda和在where扩展方法中使用func之间存在差异?

时间:2015-03-23 14:42:27

标签: c# linq lambda

我正在阅读Julia Lerman第2版的编程实体框架 我有关于示例3-5第63页的问题

书中的代码

IEnumerable<Contact> contacts5 = context.Contact.Where(c => c.FirstName == "Robert").OrderBy(foo => foo.LastName);

foreach (Contact contact in contacts5)
{
    Console.WriteLine("De voornaam is {0} en de achternaam is {1} ", contact.FirstName.Trim(), contact.LastName);
}

按预期结果

但是当我尝试

Func<Contact, bool> whereDel = c => (c.FirstName == "Robert                                            ");
Func<Contact, bool> whereDel1 = c => (c.FirstName == "Robert");
Func<Contact, string> orderDel = foo => foo.LastName;
IEnumerable<Contact> contacts6 = context.Contact.Where(whereDel).OrderBy(orderDel);

foreach (Contact contact in contacts6)
{
    Console.WriteLine("De voornaam is {0} en de achternaam is {1} ", contact.FirstName.Trim(), contact.LastName);
}

我只使用WhereDel获得预期结果。对于谓词,我从示例数据库中的数据表中复制了一个roberts。 使用whereDel1与本书示例中where子句中的lambda相同的谓词,我得到一个空的IEnumerable。 任何人吗?

1 个答案:

答案 0 :(得分:2)

EntityFramework需要Expression Func,而不只是Func。这就是它如何获得将C#-ish代码转换为SQL所需的表达式树。

IQueryable仅实现Expression Func的重载(Func已编译,而Expression<Func>未编译)。当你使用Func重载时,你正在使用IEnumerable方法 - 这意味着执行整个可查询,并在结果上应用Where,而不是将它们添加到SQL。

修复很简单:

Expression<Func<Contact, bool>> whereDel = c => c.FirstName == "Robert";

var contacts = Contact.Where(whereDel);

现在,为什么这两个会导致您获得不同的结果,而不仅仅是性能?尽管EntityFramework正在尝试做,但C#不是SQL 。评估事物之间存在差异,例如在MS SQL上,默认字符串比较不区分大小写,而C#是敏感的 - 因此,FirstName == "Robert"对MS SQL上的robert也有效,但不在C#(IEnumerable.Where变体)。另一个示例是比较两个char值(而不是varchar) - 对于char(8)FirstName = 'Robert '将在SQL中起作用,但在C#中不起作用(您需要修剪两者)双方首先)。