简体   繁体   中英

Wildcard search in LINQ to SQL query not executing

I am trying to perform a SQL "Like" wildcard search using LINQ 2 SQL with the below query

public IQueryable<DbHeader> GetHeaders()
{
    return Work.Context.Headers
        .Include(m => m.Terms.Select(t => t.MetaDataPairs))
        .Include(m => m.States)
        .Include(m => m.Attachments);
}

var dbt = from th in _objectStoreRepository.GetHeaders()
                        where SqlMethods.Like(th.CreatedBy, "test")
                        select th;

foreach (var t in dbt) {
...

However when I run this, on the foreach line I get

An unexpected error occurred: LINQ to Entities does not recognize the method 'Boolean Like(System.String, System.String)' method, and this method cannot be translated into a store expression.

Why is it considering it a LINQ to Entities query? I thought this was pure LINQ 2 SQL

to do what you want .. i usually use this Utlis .. (extension method that perform a wherelike with wildcards),.... hope it heps you

using System;
using System.Linq;
using System.Linq.Expressions;
using System.Reflection;

namespace Fwd.Repository.EF.Utils
{
    public static class LinqUtils
    {
        /// <summary>
        ///     Wheres the like.
        /// </summary>
        /// <typeparam name="TSource">The type of the source.</typeparam>
        /// <param name="source">The source.</param>
        /// <param name="valueSelector">The value selector.</param>
        /// <param name="value">The value.</param>
        /// <param name="wildcard">The wildcard.</param>
        /// <returns></returns>
        public static IQueryable<TSource> WhereLike<TSource>(this IQueryable<TSource> source,
            Expression<Func<TSource, string>> valueSelector, string value, char wildcard)
        {
            return source.Where(BuildLikeExpression(valueSelector, value, wildcard));
        }

        /// <summary>
        ///     Builds the like expression.
        /// </summary>
        /// <typeparam name="TElement">The type of the element.</typeparam>
        /// <param name="valueSelector">The value selector.</param>
        /// <param name="value">The value.</param>
        /// <param name="wildcard">The wildcard.</param>
        /// <returns></returns>
        /// <exception cref="System.ArgumentNullException">valueSelector</exception>
        public static Expression<Func<TElement, bool>> BuildLikeExpression<TElement>(
            Expression<Func<TElement, string>> valueSelector, string value, char wildcard)
        {
            if (valueSelector == null)
                throw new ArgumentNullException("valueSelector");

            var method = GetLikeMethod(value, wildcard);

            value = value.Trim(wildcard);
            var body = Expression.Call(valueSelector.Body, method, Expression.Constant(value));

            var parameter = valueSelector.Parameters.Single();
            return Expression.Lambda<Func<TElement, bool>>(body, parameter);
        }

        /// <summary>
        ///     Gets the like method.
        /// </summary>
        /// <param name="value">The value.</param>
        /// <param name="wildcard">The wildcard.</param>
        /// <returns></returns>
        private static MethodInfo GetLikeMethod(string value, char wildcard)
        {
            var methodName = "Contains";

            var textLength = value.Length;
            value = value.TrimEnd(wildcard);
            if (textLength > value.Length)
            {
                methodName = "StartsWith";
                textLength = value.Length;
            }

            value = value.TrimStart(wildcard);
            if (textLength > value.Length)
            {
                methodName = (methodName == "StartsWith") ? "Contains" : "EndsWith";
                textLength = value.Length;
            }

            var stringType = typeof(string);
            return stringType.GetMethod(methodName, new Type[] { stringType });
        }
    }
}

then you can use it on your IQueryable Entities like

var query = _dbContext.Users.WhereLike(xx=>xx.name,"fred*","*")

As the error message says, it's not Linq to SQL but Linq to Entities where the SqlMethods class is not supported ( see the Microsoft documentation ). I guess, it's because you run your query against an ObjectContext or DbContext of the Entity Framework.

On Linq to Entities the following will work:

var dbt = from th in _objectStoreRepository.GetHeaders()
          where th.CreatedBy.Contains("test")
          select th;

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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