首页 文章

如何使这个查询在LINQ to Entities中工作?

提问于
浏览
0

我必须遵循以下代码:

private static bool DoesColValueExist<T>(IQueryable dataToSearchIn, string colName, string colValue)
{
    int noOfClients = 1;
    Type type = typeof(T);
    if (colValue != "" && colName != "")
    {
        var property = type.GetProperty(colName);
        var parameter = Expression.Parameter(type, "p");
        var propertyAccess = Expression.MakeMemberAccess(parameter, property);
        Expression left = Expression.Call(propertyAccess, typeof(object).GetMethod("ToString", System.Type.EmptyTypes));
        left = Expression.Call(left, typeof(string).GetMethod("ToLower", System.Type.EmptyTypes));
        Expression right = Expression.Constant(colValue.ToLower(), typeof(string));
        MethodInfo method = typeof(string).GetMethod("Equals", new[] { typeof(string) });
        Expression searchExpression = Expression.Call(left, method, right);


        MethodCallExpression whereCallExpression = Expression.Call(
            typeof(Queryable),
            "Where",
            new Type[] { type },
            dataToSearchIn.Expression,
            Expression.Lambda<Func<T, bool>>(searchExpression, new ParameterExpression[] { parameter }));
        var searchedData = dataToSearchIn.Provider.CreateQuery(whereCallExpression);
        noOfClients = searchedData.Cast<T>().Count();

        if (noOfClients == 0)
            return false;
        else
            return true;
    }
    return true;
}

它适用于LINQ to SQL但是使用LINQ to Entities,我收到错误:

LINQ to Entities无法识别方法'System.String ToString()'方法,并且此方法无法转换为存储表达式 .

2 回答

  • 0

    Linq to Entities不支持.ToString()方法 . 我也不确定对不是字符串的类型使用字符串比较是否是一个好主意 . 但并非所有人都失去了 . 我提出了以下解决方案:

    public partial class MyEntity
    {
        public int ID { get; set; }
        public int Type { get; set; }
        public string X { get; set; }
    }
    
    public class MyContext : DbContext
    {
        public DbSet<MyEntity> Entities { get; set; }
    }
    
    class Program
    {
        static void Main(string[] args)
        {
            Database.SetInitializer(new DropCreateDatabaseIfModelChanges<MyContext>());
    
            using (var ctx = new MyContext())
            {
                if (!ctx.Entities.Any())
                {
                    ctx.Entities.Add(new MyEntity() { ID = 1, Type = 2, X = "ABC" });
                    ctx.SaveChanges();
                }
    
                Console.WriteLine(DoesColValueExist(ctx.Entities, e => e.X, "aBc"));
                Console.WriteLine(DoesColValueExist(ctx.Entities, e => e.X, "aBcD"));
                Console.WriteLine(DoesColValueExist(ctx.Entities, e => e.Type, 2));
                Console.WriteLine(DoesColValueExist(ctx.Entities, e => e.Type, 5));
    
            }
        }
    
        private static bool DoesColValueExist<TEntity, TProperty>(IQueryable<TEntity> dataToSearchIn, Expression<Func<TEntity, TProperty>> property, TProperty colValue)
        {
    
            var memberExpression = property.Body as MemberExpression;
            if (memberExpression == null || !(memberExpression.Member is PropertyInfo))
            {
                throw new ArgumentException("Property expected", "property");
            }
    
            Expression left = property.Body;
            Expression right = Expression.Constant(colValue, typeof(TProperty));
            if (typeof(TProperty) == typeof(string))
            {
                MethodInfo toLower = typeof(string).GetMethod("ToLower", new Type[0]);
                left = Expression.Call(left, toLower);
                right = Expression.Call(right, toLower);
            }
    
            Expression searchExpression = Expression.Equal(left, right);
            var lambda = Expression.Lambda<Func<TEntity, bool>>(Expression.Equal(left, right), new ParameterExpression[] { property.Parameters.Single() });
    
            return dataToSearchIn.Where(lambda).Any();                
        }
    }
    

    它的好处是它比基于字符串的解决方案更安全 - 参数的值必须与属性的值相同 . 该属性又必须是实体的成员,该实体是作为第一个参数传递的IQueryable'1的泛型类型 . 另一个有用的事情是,当对这个方法进行编码时,当你开始为第二个参数键入lambda表达式时,intellisense将显示实体的成员 . 在方法本身中,当我在属性值和请求的值上调用.ToLower()时,我为字符串类型添加了一个异常,以使比较大小写不敏感 . 对于非字符串类型,值“按原样”进行比较,即没有任何修改 . 上面的示例已完成 - 您可以将其复制并粘贴到控制台应用程序项目中(但您需要引用EntityFramework.dll) . 希望这可以帮助 .

  • 1

    试试这个:

    private static bool DoesColValueExist<T>(IQueryable dataToSearchIn, string colName, string colValue)
    {
        int noOfClients = 1;
        Type type = typeof(T);
        if (colValue != "" && colName != "")
        {
            var property = type.GetProperty(colName);
            var parameter = Expression.Parameter(type, "p");
            var propertyAccess = Expression.MakeMemberAccess(parameter, property);
            Expression left = property.PropertyType == typeof(string) ? propertyAccess : Expression.Call(propertyAccess, typeof(object).GetMethod("ToString", System.Type.EmptyTypes));
            left = Expression.Call(left, typeof(string).GetMethod("ToLower", System.Type.EmptyTypes));
            Expression right = Expression.Constant(colValue.ToLower(), typeof(string));
            MethodInfo method = typeof(string).GetMethod("Equals", new[] { typeof(string) });
            Expression searchExpression = Expression.Call(left, method, right);
    
    
            MethodCallExpression whereCallExpression = Expression.Call(
                typeof(Queryable),
                "Where",
                new Type[] { type },
                dataToSearchIn.Expression,
                Expression.Lambda<Func<T, bool>>(searchExpression, new ParameterExpression[] { parameter }));
            var searchedData = dataToSearchIn.Provider.CreateQuery(whereCallExpression);
            noOfClients = searchedData.Cast<T>().Count();
    
            if (noOfClients == 0)
                return false;
            else
                return true;
        }
        return true;
    }
    

    基本上,如果属性是字符串,那么它不会调用 ToString() 方法 .

    希望能帮助到你 .

相关问题