创建一个通过名称访问属性的LINQ to SQL兼容表达式

时间:2018-08-01 17:32:45

标签: c# linq reflection linq-to-sql

我想知道你们中的任何一个是否有解决此问题的想法。

假设有以下课程

public class Person
{
    public string Description {get; set;}
    //...
}

我想创建一个表达式,该表达式可以传递给LINQ to SQL的LINQ的Where方法中的LINQ的Where方法,例如:

Expression<Func<Person, bool>> expression = x => x.Description.Contains("foo");

这里的真正问题是,我不知道要在运行时检查哪个字段。该属性的名称以字符串形式提供(在本例中为“ Description”,但可以为“ Description2”或Person类的任何其他属性)。我不能直接在表达式本身中使用反射来获取属性值(通过使用GetTypeGetProperty等),因为在LINQ中将表达式传递给Where时表达式将不起作用到SQL,因为它无法转换为SQL代码。预先感谢!

1 个答案:

答案 0 :(得分:1)

看看这个最小的示例,所需的属性将被访问并与另一个字符串进行比较,从而产生布尔值:

// GET: People
public ActionResult Index()
{
    var propertyName = "Description";
    var compareString = "abc";

    var parameter = Expression.Parameter(typeof(Person));
    var memberAccess = Expression.MakeMemberAccess(parameter, typeof(Person).GetProperty(propertyName));
    var compare = Expression.Constant(compareString);
    var contains = Expression.Call(memberAccess, typeof(string).GetMethod(nameof(string.Contains), new[] { typeof(string) }), compare);
    var expr = Expression.Lambda<Func<Person, bool>>(contains, new[] { parameter });

    return View(db.People.Where(expr).ToList());
}

当然,这会丢失所有检查,可能的选项,缓存等。。。要点是,如果必须依赖于运行时已知类型,则必须自己创建表达式。