Linq WHERE EF.Functions.Like - 为什么直接属性有效而反射无效?

Jan*_*ryc 7 c# linq reflection entity-framework-core .net-core

我尝试在数据库站点上执行一个简单的 LIKE 操作,同时具有基于通用类型的查询构建服务。然而,我在调试时发现,EF.Functions.Like()使用反射执行并不能按预期工作:

The LINQ expression 'where __Functions_0.Like([c].GetType().GetProperty("FirstName").GetValue([c], null).ToString(), "%Test%")' could not be translated and will be evaluated locally..


与众不同的代码

这有效

var query = _context.Set<Customer>().Where(c => EF.Functions.Like(c.FirstName, "%Test%"));
Run Code Online (Sandbox Code Playgroud)

这会引发警告并尝试在内存中解决

var query = _context.Set<Customer>().Where(c => EF.Functions.Like(c.GetType().GetProperty("FirstName").GetValue(c, null).ToString(), "%Test%"));
Run Code Online (Sandbox Code Playgroud)

Linq 查询生成器或 EF.Functions 不支持反射吗?

抱歉,如果问题看起来很基本,这是我第一次尝试 .NET Core :)

Car*_*ado 11

在 EF 中,lambdasExpressionTrees,表达式被转换为 T-SQL,以便可以在数据库中执行查询

您可以像这样创建扩展方法:

public static IQueryable<T> Search<T>(this IQueryable<T> source, string propertyName, string searchTerm)
{
    if (string.IsNullOrEmpty(propertyName) || string.IsNullOrEmpty(searchTerm))
    {
        return source;
    }

    var property = typeof(T).GetProperty(propertyName);

    if (property is null)
    {
        return source;
    }

    searchTerm = "%" + searchTerm + "%";
    var itemParameter = Parameter(typeof(T), "item");

    var functions = Property(null, typeof(EF).GetProperty(nameof(EF.Functions)));
    var like = typeof(DbFunctionsExtensions).GetMethod(nameof(DbFunctionsExtensions.Like), new Type[] { functions.Type, typeof(string), typeof(string) });

    Expression expressionProperty = Property(itemParameter, property.Name);

    if (property.PropertyType != typeof(string))
    {
        expressionProperty = Call(expressionProperty, typeof(object).GetMethod(nameof(object.ToString), new Type[0]));
    }

    var selector = Call(
               null,
               like,
               functions,
               expressionProperty,
               Constant(searchTerm));

    return source.Where(Lambda<Func<T, bool>>(selector, itemParameter));
}
Run Code Online (Sandbox Code Playgroud)

并像这样使用它:

var query = _context.Set<Customer>().Search("FirstName", "Test").ToList();
var query2 = _context.Set<Customer>().Search("Age", "2").ToList();
Run Code Online (Sandbox Code Playgroud)

作为参考,这是Customer我使用的:

public class Customer
{
    [Key]
    public Guid Id { get; set; }
    public string FirstName { get; set; }
    public int Age { get; set; }
}
Run Code Online (Sandbox Code Playgroud)

  • 我只是使用静态 using,如下所示:`using static System.Linq.Expressions.Expression;` (2认同)