4

我正在编写一个 UI,允许某人通过他们的名字和/或姓氏查找用户。例如,如果您输入“Mike”作为名字,“Jo”作为姓氏,它将返回“Mike Jones”、“Mike Johnson”和“Mike Jobs”。我使用以下 LINQ 语句进行此搜索:

var users = (from u in context.TPM_USER
             where u.LASTNAME.ToLower().Contains(LastName.ToLower())
             && u.FIRSTNAME.ToLower().Contains(FirstName.ToLower())
             select u);

(可能有也可能没有更好的方法来执行不区分大小写的like子句,但这似乎有效)

问题是如果用户输入名字或姓氏,但随后将其他字段留空。如果我输入“迈克”作为名字并将姓氏字段留空,我想返回所有迈克,而不考虑他们的姓氏。上面的查询不返回任何结果,除非两个字段都至少填写了一些东西。

我试过:

var users = (from u in context.TPM_USER
             where (LastName == "" || u.LASTNAME.ToLower().Contains(LastName.ToLower()))
             && (FirstName == "" || u.FIRSTNAME.ToLower().Contains(FirstName.ToLower()))
             select u);

但是,除非两个字段都填写,否则我仍然没有得到任何结果。我已经在调试器下验证了LastName == ""确实如此。

更新:

我做了更多的调试,这实际上是一个 Oracle 问题。正在生成的查询是:

--Replaced the field list with * for brevity
SELECT * FROM TPMDBO.TPM_USER "Extent1"
     WHERE (('jones' = '') OR ((INSTR(LOWER("Extent1".LASTNAME), LOWER('jones'))) > 0)) AND (('' = '') OR ((INSTR(LOWER("Extent1".FIRSTNAME), LOWER(''))) > 0))

乍一看似乎是正确的。但是,Oracle 似乎并没有正确地缩短短语('' = ''). 事实上,如果我这样做:

select * from TPM_USER where '' = ''

我得到零行。我没有足够的 Oracle 专家知道应该如何编写此查询,但无论哪种方式,它都是实体框架方言错误。

4

5 回答 5

10

只需有条件地添加谓词:

var users = from u in context.TPM_USER select u;
if (!string.IsNullOrWhiteSpace(FirstName))
    users = users.Where(u => u.FIRSTNAME.ToLower().Contains(FirstName.ToLower()));
if (!string.IsNullOrWhiteSpace(LastName))
    users = users.Where(u => u.LASTNAME.ToLower().Contains(LastName.ToLower()));

或者仅将 LASTNAME 谓词作为条件谓词。

后期补充:

Where(u => u.FIRSTNAME.ToLower()...最好避免使用类似的表达式。它们会导致忽略任何索引FIRSTNAME,因为首先转换字段值然后进行比较(有关更多详细信息,请参见此处)。

您很有可能不需要这些小写转换。检查字段的数据库排序规则。如果它可能不区分大小写 (CI),则不需要这些转换。

于 2012-06-07T16:49:56.557 回答
2

您确定 FirstName 和 LastName 不为空吗?

你可以试试这样写...

string LowerFirstName = (FirstName + "").ToLower();
string LowerLastName = (LastName + "").ToLower();

var users = (from u in context.TPM_USER
             where (LowerLastName == "" || u.LASTNAME.ToLower().Contains(LowerLastName))
             && (LowerFirstName == "" || u.FIRSTNAME.ToLower().Contains(LowerFirstName))
             select u);
于 2012-06-07T16:51:47.590 回答
1

仅供参考,如果有人遇到 Oracle 的这个问题,这里有一个解决方法:

var users = (from u in context.TPM_USER
             where (LastName == null|| u.LASTNAME.ToLower().Contains(LastName.ToLower()))
             && (FirstName == null || u.FIRSTNAME.ToLower().Contains(FirstName.ToLower()))
             select u);

这将转换为:

'' is null

在 SQL 中,Oracle 将其解释为 true。

于 2012-06-07T20:43:17.253 回答
0

您可以简单地围绕您的查询创建一个条件语句:

if (String.IsNullOrWhiteSpace(LastName) && !String.IsNullOrWhiteSpace(FirstName))
{
   var users = (from u in context.TPM_USER
   where (u.FIRSTNAME.ToLower().Contains(FirstName.ToLower()))
   select u);
}
else if (String.IsNullOrWhiteSpace(FirstName) && !String.IsNullOrWhiteSpace(LastName))
{
   var users = (from u in context.TPM_USER
   where (u.LASTNAME.ToLower().Contains(LastName.ToLower()))
   select u);
}
于 2012-06-07T16:50:16.623 回答
0

也许您可以尝试检查搜索词的长度,看看它是否在 Oracle PL/SQL 中工作。

var users = (from u in context.TPM_USER
         where ((LastName ?? "").Trim().Length == 0 || u.LASTNAME.ToLower().Contains(LastName.ToLower()))
         && ((FirstName ?? "").Trim().Length == 0 || u.FIRSTNAME.ToLower().Contains(FirstName.ToLower()))
         select u);
于 2012-06-09T16:38:29.883 回答