Linq 实体框架4.1 object.property=value的简单动态表达式

Linq 实体框架4.1 object.property=value的简单动态表达式,linq,entity-framework,ef-code-first,Linq,Entity Framework,Ef Code First,我知道有一种方法可以使用表达式和lambda来实现这一点,但我很难将它们拼凑在一起。我所需要的只是一个方法,该方法将动态查询Entity Framework DBSet对象,以查找具有给定名称的属性与值匹配的行 我的背景: public class MyContext : DbContext { public IDbSet<Account> Accoounts{ get { return Set<Account>(); } } } 公共类MyContext:D

我知道有一种方法可以使用表达式和lambda来实现这一点,但我很难将它们拼凑在一起。我所需要的只是一个方法,该方法将动态查询Entity Framework DBSet对象,以查找具有给定名称的属性与值匹配的行

我的背景:

public class MyContext : DbContext
{
    public IDbSet<Account> Accoounts{ get { return Set<Account>(); } } 
}
公共类MyContext:DbContext
{
公共IDbSet帐户{get{return Set();}}
}
我想写的方法是:

public T Get<T>(string property, object value) : where T is Account
{...}
publictget(字符串属性,对象值):其中T是Account
{...}
我宁愿不必使用动态SQL来实现这一点,所以无需提出建议,因为我已经知道这是可能的。我真正想要的是使用表达式和lambda来帮助实现这一点


提前谢谢,我知道它很简短,但它应该是相当不言自明的。注释如果需要更多信息

动态Linq可能是一个选项。将您的条件指定为字符串,它将作为表达式生成并针对您的数据运行

我做过的事情的一个例子

var context = new DataContext(ConfigurationManager.ConnectionStrings["c"].ConnectionString);
var statusConditions = "Status = 1";
var results = (IQueryable)context.Contacts.Where(statusConditions);

动态Linq可能是一个选项。将您的条件指定为字符串,它将作为表达式生成并针对您的数据运行

我做过的事情的一个例子

var context = new DataContext(ConfigurationManager.ConnectionStrings["c"].ConnectionString);
var statusConditions = "Status = 1";
var results = (IQueryable)context.Contacts.Where(statusConditions);

我尽量避免使用动态linq,因为linq的要点是强类型访问。使用动态linq是一种解决方案,但它恰恰与linq的目的相反,而且它非常接近于使用ESQL和从sting连接构建查询。无论如何,动态linq有时是实时节省器(特别是在涉及复杂的动态排序时),我成功地将其用于一个大型项目中,使用LINQtoSQL

我通常会定义一些
SearchCriteria
类,比如:

public class SearchCriteria
{
     public string Property1 { get; set; }
     public int? Property2 { get; set; }
}
和助手查询扩展方法,如:

public static IQueryable<SomeClass> Filter(this IQueryable<SomeClass> query, SearchCriteria filter)
{
     if (filter.Property1 != null) query = query.Where(s => s.Property1 == filter.Property1);
     if (filter.Property2 != null) query = query.Where(s => s.Property2 == filter.Property2);
     return query;
}
公共静态IQueryable筛选器(此IQueryable查询、SearchCriteria筛选器)
{
if(filter.Property1!=null)query=query.Where(s=>s.Property1==filter.Property1);
if(filter.Property2!=null)query=query.Where(s=>s.Property2==filter.Property2);
返回查询;
}
这不是通用的解决方案。泛型解决方案同样适用于共享某些行为的类的强类型处理


更复杂的解决方案是自己使用谓词生成器和构建表达式树,但构建表达式树只是通过连接字符串来构建ESQL查询的更复杂的方法。

我试图尽可能避免动态linq,因为linq的主要点是强类型访问。使用动态linq是一种解决方案,但它恰恰与linq的目的相反,而且它非常接近于使用ESQL和从sting连接构建查询。无论如何,动态linq有时是实时节省器(特别是在涉及复杂的动态排序时),我成功地将其用于一个大型项目中,使用LINQtoSQL

我通常会定义一些
SearchCriteria
类,比如:

public class SearchCriteria
{
     public string Property1 { get; set; }
     public int? Property2 { get; set; }
}
和助手查询扩展方法,如:

public static IQueryable<SomeClass> Filter(this IQueryable<SomeClass> query, SearchCriteria filter)
{
     if (filter.Property1 != null) query = query.Where(s => s.Property1 == filter.Property1);
     if (filter.Property2 != null) query = query.Where(s => s.Property2 == filter.Property2);
     return query;
}
公共静态IQueryable筛选器(此IQueryable查询、SearchCriteria筛选器)
{
if(filter.Property1!=null)query=query.Where(s=>s.Property1==filter.Property1);
if(filter.Property2!=null)query=query.Where(s=>s.Property2==filter.Property2);
返回查询;
}
这不是通用的解决方案。泛型解决方案同样适用于共享某些行为的类的强类型处理


更复杂的解决方案是自己使用谓词生成器和构建表达式树,但构建表达式树只是通过连接字符串来构建ESQL查询的更复杂的方法。

以下是我的实现:

public T Get<T>(string property, object value) : where T is Account
{
    //p
    var p = Expression.Parameter(typeof(T));

    //p.Property
    var propertyExpression = Expression.Property(p, property);

    //p.Property == value
    var equalsExpression = Expression.Equal(propertyExpression, Expression.Constant(value));

    //p => p.Property == value
    var lambda = Expression.Lambda<Func<T,bool>>(equalsExpression, p);

    return context.Set<T>().SingleOrDefault(lambda);
}
publictget(字符串属性,对象值):其中T是Account
{
//p
var p=表达式参数(typeof(T));
//p、 财产
var propertyExpression=Expression.Property(p,Property);
//p、 属性==值
var equalexpression=Expression.Equal(propertyExpression,Expression.Constant(value));
//p=>p.属性==值
var lambda=表达式.lambda(等式表达式,p);
返回context.Set().SingleOrDefault(lambda);
}
它使用EF5的
Set()
方法。如果您使用的是较低版本,则需要实现一种基于
类型获取DbSet的方法


希望有帮助。

以下是我的实现:

public T Get<T>(string property, object value) : where T is Account
{
    //p
    var p = Expression.Parameter(typeof(T));

    //p.Property
    var propertyExpression = Expression.Property(p, property);

    //p.Property == value
    var equalsExpression = Expression.Equal(propertyExpression, Expression.Constant(value));

    //p => p.Property == value
    var lambda = Expression.Lambda<Func<T,bool>>(equalsExpression, p);

    return context.Set<T>().SingleOrDefault(lambda);
}
publictget(字符串属性,对象值):其中T是Account
{
//p
var p=表达式参数(typeof(T));
//p、 财产
var propertyExpression=Expression.Property(p,Property);
//p、 属性==值
var equalexpression=Expression.Equal(propertyExpression,Expression.Constant(value));
//p=>p.属性==值
var lambda=表达式.lambda(等式表达式,p);
返回context.Set().SingleOrDefault(lambda);
}
它使用EF5的
Set()
方法。如果您使用的是较低版本,则需要实现一种基于
类型获取DbSet的方法

希望能有帮助