【问题标题】:Linq search not returning all entriesLinq搜索不返回所有条目
【发布时间】:2013-07-08 12:24:11
【问题描述】:

伙计们,我有两个问题......首先我有一个 linq 查询搜索,它查询姓名和姓氏并从数据库返回结果。例如,如果我搜索 John,它将返回完美的 John travolta(我的问题是)如果我同时搜索 john travolta 的名字和姓氏,它会找不到结果?...帮助。

问题2:再次搜索时如何清除搜索结果?因为当我第二次搜索时,上一次搜索的结果是

public class SearchResults
        {
            public string Name { get; set; }
            public string Surname { get; set; }

            public SearchResults(string name, string surname)
            {
                Name = name;
                Surname = surname;
            }



 protected void btnSearch_Click(object sender, EventArgs e)
        {
            string search = txtSearch.Text.ToLower().TrimEnd();
            lsSearchResults = null;
            lsSearchResults = new List<SearchResults>();
            Repeater1.DataSource = null;
            lsSearchResults.Clear();
            Repeater1.DataSource = "";
        }

        if (string.IsNullOrWhiteSpace(txtSearch.Text))
            {
              lblResults.Text = "Please enter a password & Em@ilAddress";

                lsSearchResults.Clear();

                return;
            }

        else
        {
            var found = (from User in myDB.Memberships
                         where User.Name.ToLower().Contains(txtSearch.Text.ToLower()) ||
                         User.Surname.ToLower().Contains(txtSearch.Text.ToLower())
                         select new { User.Name, User.Surname });

            // validates items in search query if Exist
            if (!ChillZARdev.App_Code.Utilities.IsEmpty(found))
            {
                foreach (var user in found)
                {
                    lsSearchResults.Add(new SearchResults(user.Name, user.Surname));
                    // ls.Add(user.Name + " " + user.Surname);

                    // Response.Write(user);
                }
                Repeater1.DataSource = lsSearchResults;

                Repeater1.DataBind();

             }
          }

【问题讨论】:

  • 与您的问题无关,但请考虑以这种方式编写代码: lsSearchResults = (from User ... select new SearchResults(User.Name, User.Surname)).ToList();您将避免匿名类型实例化并浏览您的结果两次。

标签: c# asp.net linq


【解决方案1】:

简短的解决方案是将名字和姓氏一起包含在 where 子句中:

var found = (from User in myDB.Memberships
             where User.Name.ToLower().Contains(txtSearch.Text.ToLower()) ||
             User.Surname.ToLower().Contains(txtSearch.Text.ToLower()) ||
             (User.Name + " " + User.Surname).ToLower().Contains(txtSearch.Text.ToLower())

但是,这意味着搜索“Travolta john”不会返回任何结果。

如果这很重要,您应该用空格分隔字符串,然后搜索每个单词。

List<string> searchSplit = txtSearch.Text.ToLower().Split(' ');

var found = (from User in myDB.Memberships
         where IsMatch(searchSplit, User)

private bool IsMatch(List<string> searchSplit, User User){
   return searchSplit.Count() ==
          searchSplit.Where(x => User.Name.ToLower().Contains(x) ||
                                 User.Surname.ToLower().Contains(x)).Count();
}

理想情况下,作为Steve B has commented,最好实现一个预构建的搜索引擎,它需要比简单的自定义搜索更多的搜索工具。但这取决于您的预算/要求。

【讨论】:

  • 这意味着用户总是使用这种格式,没有多余的空间,相同的顺序,没有拼写错误。我认为正确处理要求的唯一方法是实现一个搜索引擎(Lucene.Net?Solr.Net?SharePOint?等......),它将提供更多的工具来搜索数据......但更多昂贵的解决方案
  • 非常感谢您的工作非常好...第二个问题?搜索后如何清除结果
  • 感谢@SteveB 我已将您的 cmets 添加到答案中。
  • hmmm...我认为您的方法意味着搜索“John Travolta”将返回所有名为“John”的人,无论他们的姓氏如何,这似乎是最终用户的意外行为......所有取决于您希望它如何工作
  • @musefan 你说得对,我已经更改了 IsMatch 方法的逻辑,以便拆分中的每个单词都必须匹配。
【解决方案2】:
var found = myDB.Memberships;
foreach(var word in txtSearch.Text)
{
    var word2=word;  //Must do this because word won't be right at execution
    found=found.Where(u=>u.Name.Contains(word2) || u.Surname.Contains(word2));
}

我删除了 .ToLower,因为这些列应该已经标记为不区分大小写,除非您直接更改它,或者数据库的默认区域性更改。

【讨论】:

  • 这将适用于“John”、“Travolta”、“John Tavolta”和“Travolta John”,并将在服务器端而不是客户端完成。
  • +1 用于提及使用 LINQ to SQL/EF 时的额外 .ToLower 检查。在 LINQ to Objects 中是必需的,但不是(大多数)数据库。
  • 非常感谢罗伯特,这真的很有帮助。
【解决方案3】:

几个月前,我遇到了同样的问题,我使用的是单例设计模式,而根本问题出在缓存上。对于你的两个问题,有一个解决方案 - 你可以尝试清理缓存LINQ to SQL DataContext,您可以通过以下方式做到这一点

public static void ClearCache(this DataContext context) 
 { 
    const BindingFlags FLAGS = BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic; 
    var method = context.GetType().GetMethod("ClearCache", FLAGS); 
    method.Invoke(context, null); 
 } 

你可以调用那个方法

   public void DoWork() 
     { 
        //do work... 
        dataContext.ClearCache(); 
       //do more work... 
     } 

希望对你有帮助

【讨论】:

  • 感谢 Microtechie,我尝试了您的代码,但遗憾的是失败了,我一直在尝试...解决这个问题...我不知道问题是不是我的中继器,因为结果绑定到重复。跨度>
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多