在c#中创建表达式树,使用LINQ.Expressions选择多个记录

时间:2017-12-18 10:28:07

标签: c# sql-server linq

对于以下示例学生列表,我想使用表达式树从列表中选择多个记录(以生成动态LINQ查询)

 - 1 | John  | 13
 - 2 | Steve | 15
 - 3 | Bill  | 18
 - 4 | Ram   | 12
 - 5 | Ron   | 21

用于选择单一记录

SQL Query:   
select * from studentList where StudentID = 2  

LINQ:

var studentsData = studentList.Where(s=>s.StudentID == 2).AsQueryable();

同样我需要创建表达式树,以便从值列表中选择多个记录

例如SQL Query:

From the list of IDs I need create expression for selecting records     
select * from studentList where StudentID in (2,4,3) 

示例输出:

 - 2 | Steve
 - 4 | Ram
 - 3 | Bill  

示例表达式树代码:

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

public class Program
{
public static void Main()
{
    IList<Student> studentList = new List<Student>() { 
        new Student() { StudentID = 1, StudentName = "John", Age = 13 } ,
        new Student() { StudentID = 2, StudentName = "Steve",  Age = 15 } ,
        new Student() { StudentID = 3, StudentName = "Bill",  Age = 18 } ,
        new Student() { StudentID = 4, StudentName = "Ram" , Age = 12 } ,
        new Student() { StudentID = 5, StudentName = "Ron" , Age = 21 } 
    };
    var studentwithLinQ = studentList.Where(s=>s.StudentID == 2);
    foreach(var stu in studentwithLinQ)
    Console.WriteLine("{0} | {1}",stu.StudentID, stu.StudentName);
    ParameterExpression pe = Expression.Parameter(typeof(Student), "s");
    MemberExpression me = Expression.Property(pe, "StudentID");
    int id = 2;
    ConstantExpression constant = Expression.Constant(id, typeof(int));
    BinaryExpression body = Expression.Equal(me, constant);
    Expression predicateExpression = Expression.Lambda(body, pe);
    var sourcequery = studentList.AsQueryable();
    Expression sourceExpression = Expression.Convert(Expression.Constant(sourcequery), typeof(IQueryable<Student>));
    Expression filterExpressionExpression = Expression.Constant(predicateExpression);
    var queryExpression = Expression.Call(typeof(Queryable), "Where", new Type[] { typeof(Student)}, sourceExpression,filterExpressionExpression);
    sourcequery = Expression.Lambda(queryExpression).Compile().DynamicInvoke() as IQueryable<Student>;
    Console.WriteLine("sourceExpression: {0}", sourcequery);
    var studentWithExpression = sourcequery;
    foreach(var stu in studentWithExpression)
    Console.WriteLine("{0} | {1}",stu.StudentID, stu.StudentName);
   }
 }

public class Student{
   public int StudentID { get; set; }
   public string StudentName { get; set; }
   public int Age { get; set; }
}

我可以创建用于选择单个记录的表达式代码。但我无法使用datalist.can中的多条记录选择值。请帮助我使用Expression Statments选择多个值。

2 个答案:

答案 0 :(得分:2)

我认为试图通过表达来解决这个问题。使用现有方法已经可以实现这些功能。 (这使您的解决方案更加简单化); - )

你可以试试这个:

// your original set
IList<Student> studentList = new List<Student>() { 
    new Student() { StudentID = 1, StudentName = "John", Age = 13 } ,
    new Student() { StudentID = 2, StudentName = "Steve",  Age = 15 } ,
    new Student() { StudentID = 3, StudentName = "Bill",  Age = 18 } ,
    new Student() { StudentID = 4, StudentName = "Ram" , Age = 12 } ,
    new Student() { StudentID = 5, StudentName = "Ron" , Age = 21 } 
};

// create a subselection of ids only into an array(or list) of the id's only.
// results in `int[] { 1, 2, 3, 4, 5 };`
var ids = studentList.Select(student => student.StudentID).ToArray();

// use it on the studentList.
var studentwithLinQ = studentList.Where(s => ids.Contains(s.StudentID));

ids数组将转换为IN (..)语句。

答案 1 :(得分:1)

可以为此创建一个表达式树,但这样做很难。更简单的方法是创建一个id列表:

var ids = new List<int> { 2, 3, 4 };

只需使用:

var filtered = studentList.Where(x => ids.Contains(x.StudentID));
相关问题