动态列在哪里条件

时间:2015-02-18 04:17:02

标签: c# linq expression-trees dynamicquery

在我的场景中,我想查询具有用户选择列名的表。因此,每当where条件的列名称发生更改时,我都会尝试使用lambda查询查询。

我完全不知道该怎么做,请帮我解决这个问题。或者建议是否有其他方法可以做到这一点?

string[] criteria = searchCriteria.Split('_');
var columnName = criteria[0];                        
var columnValue = criteria[1];

var subQry = (from e in ctx.tblEmployee
              where (e.DateOfJoining <= startDate || (e.DateOfJoining.Value.Month == ApplyMonth && e.DateOfJoining.Value.Year == ApplyYear)) &&
                    monInputEmployee.Contains(e.Id) == flag
              select new
              {
                  e.Id,
                  e.Code,
                  e.FName,
                  e.DateOfJoining
              }).ToList();

var eParam = Expression.Parameter(typeof(EmployeeDetail), "e");
var comparison = Expression.And(
                 Expression.Equal(Expression.Property(eParam, columnName), Expression.Constant(columnValue)),
                 Expression.Equal(Expression.Property(eParam, "CompId"), Expression.Constant(compId)));

var lambda = Expression.Lambda<Func<EmployeeDetail, bool>>(comparison, eParam);
var mainQry = subQry.Where(lambda);

3 个答案:

答案 0 :(得分:2)

@Anup,我强烈建议你建立&amp;在调用 .ToList()函数之前执行动态查询。数据库上下文包含IQueryable&lt; TEntity&gt;如果你运行任何查询,它会将所有对象加载到内存中。

构建动态表达式的函数:

static Expression<Func<T, bool>> EqualComparer<T>(string propertyName, object propertyValue)
where T : class
{
   var type = typeof (T);

   ParameterExpression input = Expression.Parameter(type);

   var prop = type.GetProperty(propertyName);

   var value = Convert.ChangeType(propertyValue, prop.PropertyType);

   var exProperty = Expression.Property(input, prop);

   var eqExpre = Expression.Equal(exProperty, Expression.Constant(value));

   return Expression.Lambda<Func<T, bool>>(eqExpre, input);
}

检查以下示例(使用内存中对象)

public class Person
{
   public string Name { get; set; }
   public uint Age { get; set; }
}

private void TestMethod()
{
    //peoples collection
    var persons = new[]
    {
        new Person {Age = 10, Name = "Ten"},
        new Person {Age = 20, Name = "Twenty"},
        new Person {Age = 30, Name = "Thirty"},
        new Person {Age = 40, Name = "Forty"},
        new Person {Age = 50, Name = "Fifty"}
    };

    //test query
    const string column = "Age";
    const int value = 20;

    //build the expression & compile
    var expression = EqualComparer<Person>(column, value).Compile();

    //run the query
    var selected =
        from p in persons
        where p.Name.Length > 0 && expression(p)
        select p;

    //iterate through results
    foreach (var person in selected)
    {
        Debug.WriteLine(person.Name);
    }
}

我希望它可以帮到你。

答案 1 :(得分:2)

以下是有用的文章Build Where Clause Dynamically in Linq,请查看Joe Albahari撰写的PredicateBuilder。 您可以使用Where clause重写PredicateBuilder,如下所示:

配偶你有SearchCriteria模型。

Public class SearchCritera 
{
    public DateTime? DateOfJoining { get; set; }
    public int? CompanyId { get; set; }
    public int? CategoryId { get; set; }
    public EmployeeStatus? EmpStatus { get; set; }
}

var whereClause = PredicateBuilder.True<tblEmployee>();
if (searchCriteria.CompanyId.HasValue)
    whereClause = whereClause.And(r => r.CompanyId == searchCriteria.CompanyId);

if (searchCriteria.CategoryId.HasValue)
    whereClause = whereClause.And(r => r.Category == searchCriteria.CategoryId);

if (searchCriteria.CategoryId.HasValue)
    whereClause = whereClause.And(r => r.EmpStatus == searchCriteria.EmpStatus);

if (searchCriteria.DateOfJoining.HasValue)
{
    var dateClause1 = PredicateBuilder.True<tblEmployee>();
    dateClause1.And(r => r.DateOfJoining <= searchCriteria.DateOfJoining);

    var dateClause2 = PredicateBuilder.True<tblEmployee>();
    dateClause2.And(r => re.DateOfJoining.Value.Month == searchCriteria.DateOfJoining.Month);
    dateClause2.And(r => re.DateOfJoining.Value.Year == searchCriteria.DateOfJoining.Year);
    dateClause1.Or(dateClause2);

    whereClause.And(dateClause1)
}

var result = ctx.tblEmployee.AsExpandable().Where(whereClause);

答案 2 :(得分:2)

这就是我如何解决它,只需在Where添加一个额外的lambda: -

string[] criteria = searchCriteria.Split('_');
var columnName = criteria[0];                        
var columnValue = criteria[1];

var eParam = Expression.Parameter(typeof(EmployeeDetail), "e");
var comparison = Expression.Equal(Expression.Property(eParam, columnName), Expression.Convert(Expression.Constant(columnValue), Expression.Property(eParam, columnName).Type));

var lambda = Expression.Lambda<Func<EmployeeDetail, bool>>(comparison, eParam);

var subQry = (from e in ctx.tblEmployee
              where (e.DateOfJoining <= startDate || (e.DateOfJoining.Value.Month == ApplyMonth && e.DateOfJoining.Value.Year == ApplyYear)) &&
                    monInputEmployee.Contains(e.Id) == flag
              select new
              {
                  e.Id,
                  e.Code,
                  e.FName,
                  e.DateOfJoining
              }).Where(lambda)
                .ToList();