【问题标题】:Lambda Filtering using StartsWith is not working in c#使用 StartsWith 的 Lambda 过滤在 c# 中不起作用
【发布时间】:2018-08-30 20:23:16
【问题描述】:

我正在使用 Lambda 表达式进行搜索。我正在搜索 3 个字段,即姓名、地址、电子邮件。我在控制器的视图中编写了以下 lambda 表达式:

return View(db.SalesPersons.Where(x => x.Name.StartsWith(search.ToUpper()) || x.Address.StartsWith(search.ToUpper()) || x.Email.StartsWith(search.ToUpper())).ToList().ToPagedList(page ?? 1, 3));

但是当我调试应用程序时,它正在生成以下 sql:

SELECT 
    [Extent1].[IID] AS [IID], 
    [Extent1].[Name] AS [Name], 
    [Extent1].[Address] AS [Address], 
    [Extent1].[City] AS [City], 
    [Extent1].[Pin] AS [Pin], 
    [Extent1].[UserId] AS [UserId], 
    [Extent1].[Password] AS [Password], 
    [Extent1].[ContactNo1] AS [ContactNo1], 
    [Extent1].[ContactNo2] AS [ContactNo2], 
    [Extent1].[Email] AS [Email]
    FROM [dbo].[SalesPerson] AS [Extent1]

显然缺少 where 原因。所以它返回所有记录而不过滤。我不确定是什么问题。有什么线索吗?

谢谢

帕萨

【问题讨论】:

  • it is generating following sql: 你是怎么测试的?
  • StartsWith 和 ToUpper 的组合对我来说看起来很臭。您可以尝试将大写字符串存储在新的 c# 变量中并将其传递给 StartsWith 吗?
  • 所有非空字符串以string.Empty.开头:见dotnetfiddle.net/ON22le
  • "调试时获取sql。"没错,但是如果您的代码看起来像您所显示的那样,我认为您很可能以错误的方式获取 SQL。尝试将您的 IQueryable(ToList() 调用之前的所有内容)提取到一个单独的变量中。然后在声明该变量后停止并检查该 IQueryable 上的ToString()。仔细检查 search 是否具有您认为的值也是很好的。
  • 确保您始终可以在数据库上运行分析器 :-)

标签: c# entity-framework linq lambda


【解决方案1】:

砍掉 where 的另一个原因是查询的优化:

如果searchstring.Empty

然后

"your string".StartsWith(string.Empty)

总是返回 true。


另一方面:
string s = null;
s.StartsWith(string.Empty);

会抛出错误。


为了确保您的 search 变量具有适当的值,您可以执行以下操作来排除 string.Empty 情况:

var newSearch = "hi".ToUpper();
db.SalesPersons.Where(x => x.Name.StartsWith(newSearch) ||
                           x.Address.StartsWith(newSearch) || 
                           x.Email.StartsWith(newSearch))

没有帮助?您可以尝试使用分析器,以确保这是进入数据库的实际 SQL,如果是:提交错误。

【讨论】:

    【解决方案2】:

    WHERE 子句可能被砍掉的一个原因是 EF 提供程序无法识别 ToUpper,并决定在内存中运行该部分查询。

    您可以通过在查询之外执行ToUpper 来解决此问题,如下所示:

    var upperSearch = search.ToUpper();
    return View(db.SalesPersons.Where(x =>
        x.Name.StartsWith(upperSearch)
    ||  x.Address.StartsWith(upperSearch)
    ||  x.Email.StartsWith(upperSearch)
    ).ToList().ToPagedList(page ?? 1, 3));
    

    【讨论】:

    • 我不知道 EF 决定隐式“在内存中运行”。如果它不能我们到 Upper,它应该抛出异常 IMO。
    • 该问题中接受的答案指出 EF 可以翻译 ToLower,因此恕我直言,它与 ToUpper 或 StartsWith 无关。问题是:stackoverflow.com/questions/13885885/…
    • @Stefan 我有理由确定其中一个 EF(EF 核心?)足够聪明,可以为无法转换为 RDBMS 的事情执行隐含的AsEnumerable()。不过,我不确定它是什么版本,因为那时我切换到 Dapper :-)
    • @Stefan 查询构建器和查询提供者负责决定是否/何时/如何执行查询。对于标准的 EF 提供程序,他们通常会尽最大努力将事情转化为(例如)SQL,但当无法确定如何运行时,也会退回到查询结果的内存枚举它们在 sql server 上的查询 / 中。
    • 啊,小巧玲珑......很好......顺便说一句,ToUpper 可以翻译成@EmreSavcı 问题所表明的那样。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2012-11-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-12-02
    相关资源
    最近更新 更多