我正在编写一个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);
(可能有或没有更好的方法来做一个不区分大小写的喜欢子句,但这似乎有效)
问题是如果用户输入名字或姓氏,但是将另一个字段留空。如果我输入“Mike”作为名字并将Last Name字段留空,我想要返回所有Mikes而不管他们的姓氏。除非两个字段都至少填充了某些内容,否则上述查询不会返回任何结果。
我试过了:
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查询应该编写的Oracle专家,但无论如何都是一个实体框架方言错误。
答案 0 :(得分:9)
只需有条件地添加谓词:
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
上的任何索引被忽略,因为首先转换字段值然后进行比较(有关详细信息,请参阅here)。
您很有可能不需要这些小写转换。检查字段的数据库排序规则。如果它不区分大小写(CI),那么您可能不需要这些转换。
答案 1 :(得分: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);
答案 2 :(得分: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。
答案 3 :(得分: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);
}
答案 4 :(得分: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);