解决方法从泛型方法中的查询中获取无效的LINQ方法

时间:2013-01-30 07:20:13

标签: c# linq entity-framework generics

我正在尝试使用以下通用方法来搜索数据库中的实体:

    // 'atributo' is the name of the attribute to search against
    public List<TEntity> buscar<TEntity>(string valor, string atributo) where TEntity : class
    {
        var matches = from m in db.Set<TEntity>()
                      where m.GetType().GetProperty(atributo).GetValue(m, null).ToString().Contains(valor)
                      select m;

        return matches.ToList();
    }

当然我得到了例外:

LINQ to Entities无法识别方法'System.String ToString()'方法

我知道GetType(),GetProperty()和GetValue()也是无效的LINQ方法。

我无法弄清楚如何在查询之前使用无效方法。

有什么想法吗?

TIA

3 个答案:

答案 0 :(得分:4)

您可以自己编写表达式树(动态LINQ对您的需求来说太过分了):

using System;
using System.Collections.Generic;
using System.Data.Entity;
using System.Linq;
using System.Linq.Expressions;

class YourClass
{
    public static List<TEntity> DoSomething<TEntity>(DbContext db, string valor, string atributo)
        where TEntity : class
    {
        var mParam = Expression.Parameter(typeof(TEntity));

        var matches = db.Set<TEntity>()
                        .Where(Expression.Lambda<Func<TEntity, bool>>(
                            Expression.Call(
                                Expression.Convert(
                                    Expression.Property(mParam, atributo),
                                    typeof(String)
                                    ),
                                "Contains",
                                new Type[0],
                                Expression.Constant(valor)
                                ),
                            mParam
                         ));

        return matches.ToList();
    }
}

注意:

  1. 如果未在TEntity上定义属性(即使TEntity是抽象的且所有子类执行定义属性),那将无效;
  2. 如果知道该属性的返回类型为String,则可以避免Expression.Convert调用;
  3. 如果Entity Framework无法将属性的值转换为字符串(例如,如果属性返回实体类型),则无效;

答案 1 :(得分:0)

linq to entities将linq转换为表达式树,然后尝试将该表达式树转换为SQL。它不会评估表达式,因此无法将反射代码转换为SQL。您可以做的是使用dynamic linq您的代码将类似于

public List<TEntity> buscar<TEntity>(string valor, string atributo) where TEntity : class
{
    return db.Set<TEntity>()
           .Where(atributo + =".Contains(\"" + valor + "\")")
           .ToList()
}

答案 2 :(得分:-1)

更新

SqlFunctions.StringConvert(m.GetType().GetProperty(atributo).GetValue(m, null))