【问题标题】:MySQL Linq using .Contains(variable)MySQL Linq 使用 .Contains(variable)
【发布时间】:2015-02-04 22:25:59
【问题描述】:

设置信息:

  • VS2013 / C#
  • EF6
  • MySQL 数据库
  • .Net 连接器 6.9.5

我正在尝试创建一个使用部分名称作为搜索条件返回帐户记录集合的方法。如果我使用 IQueryable .Contains() 扩展方法对字符串值进行硬编码,它会返回数据。但是,当我尝试使用变量时,不会返回任何数据。

Public class Test() {

MyEntities db = new MyEntities();

//Works....but the search criteria is hard coded.
  public IQueryable<Account> WorksButValueHardCoded() {

    return (from a in db.Accounts
           where a.accountname.Contains("Test")
           select a);
  }

//Does not return anything
  public IQueryable<Account> DoesNotReturnAnyData() {

    //Obviously I would use a parameter, but even this test fails
    string searchText = "Test";  

    return (from a in db.Accounts
           where a.accountname.Contains(searchText)
           select a);
  }
}

我可以在 LINQ 生成的 SQL 中看到使用 LIKE 运算符,但我不明白变量是如何注入的:

SELECT
`Extent1`.`accountid`, 
`Extent1`.`accountname`
FROM `account` AS `Extent1`
WHERE `Extent1`.`accountname` LIKE '%p__linq__0%'

那么...为什么它适用于硬编码值而不是字符串变量?

【问题讨论】:

标签: c# mysql linq entity-framework contains


【解决方案1】:

理论上我看不出有什么问题

更新

这对我来说在 sqlServer 上工作得很好

public IQueryable<Account> DoesNotReturnAnyData(MyEntities db,string searchText) {
    return (from a in db.Accounts
        where a.accountname.Contains(searchText )
        select a)
}

【讨论】:

  • 是的,你是对的,上下文在返回之前被处理(我已经更改为使用上下文的类属性)使用 .ToList() 函数确实会强制查询。我试过了,但结果是一样的。硬编码时有效,使用字符串变量时无效。
  • 我知道 MySQL 的最新 .Net 连接器中的 .Contains、.StartsWith 和 .EndsWith 扩展名发生了一些变化,这与关键字“LIKE”的使用有关。我几乎想知道这是否是一个新错误。有没有其他方法可以做同样的事情,我可以测试?
  • 刚刚更新,以上在 SQL 服务器上运行良好,你可能是对的,但是我不使用 mysql,所以很遗憾我无法为你测试
  • 我想你可以试试 StartsWith 甚至直接比较 Ie == 与你的 searchText,看看会发生什么
  • a.accountname.StartWith(searchText) 失败的地方
【解决方案2】:

我遇到了同样的问题,并使用 Glimpse 一步一步地跟踪错误(检查服务器正在做什么的好工具)。事实证明,SQL 语句是正确构建的,因为我通过在数据库上执行它得到了结果。 问题可能是替换语句中的字符串变量。我猜 LINQ 不只是替换你传递的字符串,而是用空格填充变量到 VARCHAR 限制,所以你的查询看起来像

SELECT`Extent1`.`accountid`, `Extent1`.`accountname`
FROM `account` AS `Extent1`
WHERE `Extent1`.`accountname` LIKE '%Test                ...       %'

添加

.Trim()

到你的字符串,它的工作原理。

public IQueryable<Account> DoesNotReturnAnyData() {
    string searchText = "Test";

    // Use Trim() here
    return (from a in db.Accounts
       where a.accountname.Contains(searchText.Trim())
       select a);
}

【讨论】:

    【解决方案3】:

    这是 MySQL Entity Framework 6.9.5 报告的错误

    错误 #74918:Entity Framework 6 的查询结果不正确: https://bugs.mysql.com/bug.php?id=74918

    已在 MySQL Connector/Net 6.7.7 / 6.8.5 / 6.9.6 版本中修复。

    变更日志: 使用 Entity Framework 6,传入对“StartWith”的字符串引用 子句会返回不正确的结果。

    或者,一种解决方法是使用.Substring(0),这会强制实体不使用LIKE(可能会影响性能)。

    return (from a in db.Accounts
        where a.accountname.Contains(searchText.Substring(0))
    

    【讨论】:

      猜你喜欢
      • 2017-03-11
      • 2022-10-15
      • 2011-08-07
      • 1970-01-01
      • 2010-09-16
      • 1970-01-01
      • 2011-01-23
      • 1970-01-01
      • 2013-01-22
      相关资源
      最近更新 更多