示例#1
0
        public bool Check()
        {
            IEqualityComparer <IResultSet> comparer = null;

            if (this.ordered)
            {
                comparer = new OrderedResultSetComparer();
            }
            else
            {
                comparer = new ResultSetComparer();
            }

            return(comparer.Equals(this.Expected, this.Actual));
        }
示例#2
0
        public bool Check()
        {
            IEqualityComparer<IResultSet> comparer = null;

            if (this.ordered)
            {
                comparer = new OrderedResultSetComparer();
            }
            else
            {
                comparer = new ResultSetComparer();
            }

            return comparer.Equals(this.Expected, this.Actual);
        }
        /// <summary>
        /// A natural language search interprets the search string as a phrase in natural human language
        /// This model works further into the expression tree ,  the DbSet is retrieved from the
        ///  thisQueryable so its bound to a specific version of Entity framework (this one is 2.X)
        /// </summary>
        /// <typeparam name="TEntity"></typeparam>
        /// <param name="thisQueryable">the IQueryable from an enabled DbSet</param>
        /// <param name="searchText">search command</param>
        /// <param name="orderedComparer">an ordered list comparator returned for use in sorting the results in ranking order</param>
        /// <returns></returns>
        public static IQueryable <TEntity> NaturalLanguageFullTextSearch <TEntity>(this IQueryable <TEntity> thisQueryable, string searchText, out OrderedResultSetComparer <TEntity> orderedComparer) where TEntity : class
        {
            //warning this is a cheat
            DbContext       dbCtx = thisQueryable.GetDbContext();
            DbSet <TEntity> dbSet = dbCtx.Set <TEntity>();

            return(dbSet.NaturalLanguageFullTextSearch(searchText, out orderedComparer));
        }
        /// <summary>
        /// A natural language search interprets the search string as a phrase in natural human language
        /// </summary>
        /// <typeparam name="TEntity"></typeparam>
        /// <param name="thisDbSet">the DbSet from an enabled DbContext</param>
        /// <param name="searchText">search command</param>
        ///<param name="orderByScore">order the results by score</param>
        /// <returns></returns>
        private static IQueryable <TEntity> FullTextSearchInternal <TEntity>(this DbSet <TEntity> thisDbSet, string searchText, string[] columnNames, bool booleanMode, bool queryExpansion, bool orderByScore, out OrderedResultSetComparer <TEntity> orderedComparer) where TEntity : class
        {
            Type entityType = typeof(TEntity);
            IQueryable <TEntity> queryableDbSet = thisDbSet as IQueryable <TEntity>;
            DbContext            dbCtx          = thisDbSet.GetDbContext <TEntity>();
            string tableName = dbCtx.GetActualTableName(entityType);

            string[] entityKeyNames = GetKeyColumnNamesAndTypes(entityType, out Type[] keyColumnTypes);
            if (entityKeyNames.Length == 0 || entityKeyNames.Length > 1)
            {
                throw new FullTextQueryException(typeof(TEntity).Name + " as (" + tableName + ") does not have a single unique Key.");
            }

            if (null == columnNames || columnNames.Length == 0)
            {
                throw new FullTextQueryException(typeof(TEntity).Name + " as (" + tableName + ") does not have any FullTextAttributes.");
            }
            //Ok its a good query so compose an execute a query to retrive the Key property values
            //that match the query and convert this to an Queryable expression that finds any
            //additional clauses in a List of those key values
            //Now get the untyped collection of results from the query
            ArrayList untypedResults = ExecuteFullTextSearch(dbCtx, tableName, entityKeyNames[0], searchText, columnNames, booleanMode, queryExpansion, orderByScore);

            //Ok get the matching TEntity parameter
            ParameterExpression parameterExpression = Expression.Parameter(queryableDbSet.ElementType, "p");
            //And now project the propery name on TEntity
            MemberExpression memberPropertyAccess = MemberExpression.Property(parameterExpression, entityKeyNames[0]);
            // Convert the results to a typed collection so that the comparisonCondition can be correctly constructed , if we dont
            //  we will get errors like this (assuming a key of type guid and an untyped array)
            //  " generic type 'System.Guid' cannot be used for parameter of type 'System.Object' of method 'Boolean Contains(System.Object)'"
            Expression       comparisonCondition = null;
            LambdaExpression lambdaExpression    = null;
            MethodInfo       containsMethod      = null;

            orderedComparer = null;
            if (keyColumnTypes[0] == typeof(Guid))
            {
                List <Guid> containedIn = ConvertUntypedCollectionToTypedList <Guid>(untypedResults);
                containsMethod      = typeof(List <Guid>).GetMethod("Contains", new Type[] { typeof(Guid) });
                comparisonCondition = Expression.Call(Expression.Constant(containedIn), containsMethod, memberPropertyAccess);
                lambdaExpression    = Expression.Lambda(comparisonCondition, parameterExpression);
                if (orderByScore)
                {
                    orderedComparer = new OrderedResultSetComparer <TEntity>(containedIn, entityKeyNames[0]);
                }
            }
            else if (keyColumnTypes[0] == typeof(string))
            {
                List <string> containedIn = ConvertUntypedCollectionToTypedList <string>(untypedResults);
                containsMethod      = typeof(List <string>).GetMethod("Contains", new Type[] { typeof(string) });
                comparisonCondition = Expression.Call(Expression.Constant(containedIn), containsMethod, memberPropertyAccess);
                lambdaExpression    = Expression.Lambda(comparisonCondition, parameterExpression);
                if (orderByScore)
                {
                    orderedComparer = new OrderedResultSetComparer <TEntity>(containedIn, entityKeyNames[0]);
                }
            }
            else if (keyColumnTypes[0] == typeof(int))
            {
                List <int> containedIn = ConvertUntypedCollectionToTypedList <int>(untypedResults);
                containsMethod      = typeof(List <int>).GetMethod("Contains", new Type[] { typeof(int) });
                comparisonCondition = Expression.Call(Expression.Constant(containedIn), containsMethod, memberPropertyAccess);
                lambdaExpression    = Expression.Lambda(comparisonCondition, parameterExpression);
                if (orderByScore)
                {
                    orderedComparer = new OrderedResultSetComparer <TEntity>(containedIn, entityKeyNames[0]);
                }
            }
            else if (keyColumnTypes[0] == typeof(Int64))
            {
                List <Int64> containedIn = ConvertUntypedCollectionToTypedList <Int64>(untypedResults);
                containsMethod      = typeof(List <Int64>).GetMethod("Contains", new Type[] { typeof(Int64) });
                comparisonCondition = Expression.Call(Expression.Constant(containedIn), containsMethod, memberPropertyAccess);
                lambdaExpression    = Expression.Lambda(comparisonCondition, parameterExpression);
                if (orderByScore)
                {
                    orderedComparer = new OrderedResultSetComparer <TEntity>(containedIn, entityKeyNames[0]);
                }
            }
            else if (keyColumnTypes[0] == typeof(Int16))
            {
                List <Int16> containedIn = ConvertUntypedCollectionToTypedList <Int16>(untypedResults);
                containsMethod      = typeof(List <Int16>).GetMethod("Contains", new Type[] { typeof(Int16) });
                comparisonCondition = Expression.Call(Expression.Constant(containedIn), containsMethod, memberPropertyAccess);
                lambdaExpression    = Expression.Lambda(comparisonCondition, parameterExpression);
                if (orderByScore)
                {
                    orderedComparer = new OrderedResultSetComparer <TEntity>(containedIn, entityKeyNames[0]);
                }
            }
            else
            {
                throw new FullTextQueryException("unsupported primary key type " + keyColumnTypes[0].Name + " for " + tableName);
            }

            //now update the query expression to a "contains" for the type of the object in the list we just returned
            MethodCallExpression conditionResult = Expression.Call(typeof(Queryable), "Where", new[] { queryableDbSet.ElementType }, queryableDbSet.Expression, lambdaExpression);

            return(queryableDbSet.Provider.CreateQuery <TEntity>(conditionResult));
        }
        /// <summary>
        /// A natural language with query expansion search is a modification of a natural language search. The search string is used to perform a natural language search.
        /// Then words from the most relevant rows returned by the search are added to the search string and the search is done again. The query returns the rows from the second search.
        /// </summary>
        /// <typeparam name="TEntity"></typeparam>
        /// <param name="thisDbSet">the DbSet from an enabled DbContext</param>
        /// <param name="searchText">search command</param>
        /// <param name="orderedComparer">an ordered list comparator returned for use in sorting the results in ranking order</param>
        /// <returns></returns>
        public static IQueryable <TEntity> NaturalLanguageFullTextSearchWithQueryExpansion <TEntity>(this DbSet <TEntity> thisDbSet, string searchText, out OrderedResultSetComparer <TEntity> orderedComparer) where TEntity : class
        {
            Type entityType = typeof(TEntity);

            string[]             columnNames = GetFullTextColumnNames(entityType);
            IQueryable <TEntity> returnValue = thisDbSet.FullTextSearchInternal(searchText, columnNames, false, true, true, out orderedComparer);

            return(returnValue);
        }