繁体   English   中英

使用Entity Framework在数据库中搜索文本

[英]Searching for text in a database with Entity Framework

我正在编写一个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 '' = ''

我得零行。 我没有足够的甲骨文专家知道这个查询应该如何写的,但无论哪种方式,它是一个实体框架方言错误。

只需有条件地添加谓词:

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)(可能是它),则不需要这些转换。

你确定FirstName和LastName不是null吗?

你可以尝试这样写它......

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);

仅供参考,如果有人遇到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。

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

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);
}

您可以尝试检查搜索词的长度,看它是否在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);

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM