A “Composable” Full Text Search with a Code First Model

前端 未结 2 1022
醉梦人生
醉梦人生 2020-12-08 11:55

UPDATE 18 Sep 2013

It looks like there isn\'t an easy way to do this. I\'m holding out for a solution that involves some extension to Entity Framewo

2条回答
  •  自闭症患者
    2020-12-08 12:29

    I had this same issue recently: EF 5 Code First FTS Queriable

    Let me extend that post.

    • Your first option was mine first as well - using SqlQuery I also needed to do more filtering, so instead of always writing full sql I used QueryBuilder, to which I made some changes and added more functions to fit my needs(I could upload it somewhere if needed): QueryBuilder

    • After I have found another idea which I implemented. Someone already mention it here, and that is to use SqlQuery that will return HashSet of Ids and that you can use it in EF queries with Contains. This is better but not most optimal since you need 2 queries and Id list in memory. Example:

          public IQueryable FullTextSearchCompaniesByName(int limit, int offset, string input, Guid accountingBureauId, string orderByColumn)
      {
          FtsQueryBuilder ftsQueryBuilder = new FtsQueryBuilder();
      
          ftsQueryBuilder.Input = FtsQueryBuilder.FormatQuery(input);
          ftsQueryBuilder.TableName = FtsQueryBuilder.GetTableName();
          ftsQueryBuilder.OrderByTable = ftsQueryBuilder.TableName;
          ftsQueryBuilder.OrderByColumn = orderByColumn;
          ftsQueryBuilder.Columns.Add("CompanyId");
      
          if (accountingBureauId != null && accountingBureauId != Guid.Empty)
              ftsQueryBuilder.AddConditionQuery(Condition.And, "" , @"dbo.""Company"".""AccountingBureauId""", Operator.Equals, accountingBureauId, "AccountingBureauId", "");
      
          ftsQueryBuilder.AddConditionQuery(Condition.And, "", @"dbo.""Company"".""Deleted""", Operator.Equals, false, "Deleted", "");
      
          var companiesQuery = ftsQueryBuilder.BuildAndExecuteFtsQuery(Context, limit, offset, "Name");
          TotalCountQuery = ftsQueryBuilder.Total;
          HashSet companiesIdSet = new HashSet(companiesQuery);
          var q = Query().Where(a => companiesIdSet.Contains(a.CompanyId));
          return q;
      }
      
    • However EF 6 now has something called Interceptors that can be used to implement queriable FTS, and it is pretty simple and generic(last post): EF 6 Interceptors for FTS. I have tested this and it works fine.

    !! REMARK: EF Code First, even with version 6, does not support Custom Stored Procedures. There are only some for predefined CUD operations if I understood it well: Code First Insert/Update/Delete Stored Procedure Mapping, so it can't be done with it.

    Conclusion: if you can use EF 6 go for third options, is gives all you need. If you are stucked with EF 5 or less, second option is better then first but not most optimal.

提交回复
热议问题