使用Intersect I获取Local序列不能用于查询运算符的LINQ to SQL实现,但Contains运算符除外

时间:2012-06-15 16:59:37

标签: c# linq-to-sql sequence local intersect

我正在使用Linq to SQL查询来提供针对数据库字段的搜索词匹配列表。搜索项是内存字符串数组。具体来说,我在Linq查询中使用“交叉”,将搜索项与数据库字段“描述”进行比较。在下面的代码中,description字段是iss.description。描述字段在Linq查询中被分成一个数组,而交叉用于比较搜索项和描述项,以保留Linq查询中的所有比较和条件,以便不对数据库征税。在我的研究中,尝试克服这个问题,我发现不支持使用内存或“本地”序列。我在研究期间也尝试了一些建议,比如使用“AsEnumerable”或“AsQueryable”而没有成功。

searchText = searchText.ToUpper();
var searchTerms = searchText.Split(' ');

var issuesList1 = (
    from iss in DatabaseConnection.CustomerIssues

    let desc = iss.Description.ToUpper().Split(' ')
    let count = desc.Intersect(searchTerms).Count()
    where desc.Intersect(searchTerms).Count() > 0

    join stoi in DatabaseConnection.SolutionToIssues on iss.IssueID equals stoi.IssueID into stoiToiss
    from stTois in stoiToiss.DefaultIfEmpty()
    join solJoin in DatabaseConnection.Solutions on stTois.SolutionID equals solJoin.SolutionID into solutionJoin
    from solution in solutionJoin.DefaultIfEmpty()
    select new IssuesAndSolutions
    {
        IssueID = iss.IssueID,
        IssueDesc = iss.Description,
        SearchHits = count,
        SolutionDesc = (solution.Description == null)? "No Solutions":solution.Description,
        SolutionID = (solution.SolutionID == null) ? 0 : solution.SolutionID,
        SolutionToIssueID = (stTois.SolutionToIssueID == null) ? 0 : stTois.SolutionToIssueID,
        Successful = (stTois.Successful == null)? false : stTois.Successful
    }).ToList();
    ...

我成功的唯一方法是创建两个查询并调用如下所示的方法,但这需要Linq查询返回所有匹配结果(包含描述中搜索项的匹配数),包括不匹配的记录并提供内存列表<>然后使用另一个Linq查询过滤掉不匹配的记录。

public static int CountHits(string[] searchTerms, string Description)
    {
        int hits = 0;
        foreach (string item in searchTerms)
        {
            if (Description.ToUpper().Contains(item.Trim().ToUpper())) hits++;
        }            
        return hits;
    }
    public static List<IssuesAndSolutions> SearchIssuesAndSolutions(string searchText)
    {
        using (BYCNCDatabaseDataContext DatabaseConnection = new BYCNCDatabaseDataContext())
        {
            searchText = searchText.ToUpper();
            var searchTerms = searchText.Split(' ');

            var issuesList1 = (
                from iss in DatabaseConnection.CustomerIssues
                join stoi in DatabaseConnection.SolutionToIssues on iss.IssueID equals stoi.IssueID into stoiToiss
                from stTois in stoiToiss.DefaultIfEmpty()
                join solJoin in DatabaseConnection.Solutions on stTois.SolutionID equals solJoin.SolutionID into solutionJoin
                from solution in solutionJoin.DefaultIfEmpty()
                select new IssuesAndSolutions
                {
                    IssueID = iss.IssueID,
                    IssueDesc = iss.Description,
                    SearchHits = CountHits(searchTerms, iss.Description),
                    SolutionDesc = (solution.Description == null)? "No Solutions":solution.Description,
                    SolutionID = (solution.SolutionID == null) ? 0 : solution.SolutionID,
                    SolutionToIssueID = (stTois.SolutionToIssueID == null) ? 0 : stTois.SolutionToIssueID,
                    Successful = (stTois.Successful == null)? false : stTois.Successful
                }).ToList();

            var issuesList = (
                from iss in issuesList1
                where iss.SearchHits > 0
                select iss).ToList();
                ...

我会对两个Linq查询感到满意,但是第一个Linq查询只返回匹配的记录,然后可能使用第二个,也许是lambda表达式来排序它们,但我的试验没有成功。

非常感谢任何帮助。

1 个答案:

答案 0 :(得分:0)

好的,所以在经过更多搜索更多技术并尝试使用user1010609的技术之后,我设法在几乎完全重写之后才能使它工作。以下代码首先提供具有我正在搜索的所有信息的平面记录查询,然后形成新列表,其中过滤后的信息与搜索项进行比较(计算每个搜索项的命中数以按相关性排序)。我小心不要返回平面文件的列表,因此在最终的数据库检索中(在形成过滤的List&lt;&gt;期间)会有一些效率。我很肯定这甚至不是一种有效的方法,但它确实有效。我渴望看到更多和独特的技术来解决这类问题。谢谢!

searchText = searchText.ToUpper();
List<string> searchTerms = searchText.Split(' ').ToList();

var allIssues =
    from iss in DatabaseConnection.CustomerIssues
    join stoi in DatabaseConnection.SolutionToIssues on iss.IssueID equals stoi.IssueID into stoiToiss
    from stTois in stoiToiss.DefaultIfEmpty()
    join solJoin in DatabaseConnection.Solutions on stTois.SolutionID equals solJoin.SolutionID into solutionJoin
    from solution in solutionJoin.DefaultIfEmpty()
    select new IssuesAndSolutions
    {
        IssueID = iss.IssueID,
        IssueDesc = iss.Description,
        SolutionDesc = (solution.Description == null) ? "No Solutions" : solution.Description,
        SolutionID = (solution.SolutionID == null) ? 0 : solution.SolutionID,
        SolutionToIssueID = (stTois.SolutionToIssueID == null) ? 0 : stTois.SolutionToIssueID,
        Successful = (stTois.Successful == null) ? false : stTois.Successful
    };                

    List<IssuesAndSolutions> filteredIssues = new List<IssuesAndSolutions>();

    foreach (var issue in allIssues)
    {
        int hits = 0;
        foreach (var term in searchTerms)
        {
            if (issue.IssueDesc.ToUpper().Contains(term.Trim())) hits++;                        
        }
        if (hits > 0)
        {
             IssuesAndSolutions matchedIssue = new IssuesAndSolutions();
             matchedIssue.IssueID = issue.IssueID;
             matchedIssue.IssueDesc = issue.IssueDesc;
             matchedIssue.SearchHits = hits;
             matchedIssue.CustomerID = issue.CustomerID;
             matchedIssue.AssemblyID = issue.AssemblyID;
             matchedIssue.DateOfIssue = issue.DateOfIssue;
             matchedIssue.DateOfResolution = issue.DateOfResolution;
             matchedIssue.CostOFIssue = issue.CostOFIssue;
             matchedIssue.ProductID = issue.ProductID;
             filteredIssues.Add(matchedIssue);
         }                    
      }