2013-02-07 19 views
5

Tôi đang cố gắng để tạo ra một truy vấn động sử dụng cây biểu thức để phù hợp với tuyên bố sau:Sử dụng Chọn phương pháp cho các truy vấn năng động và cây biểu

var items = data.Where(i => i.CoverageType == 2).Select(i => i.LimitSelected); 

tôi có thể tạo ra các phương pháp ở đâu và có được một kết quả từ nó; tuy nhiên, tôi không thể tạo phương thức chọn.

Đây là nơi phương pháp của tôi:

var parm = Expression.Parameter(typeof(BaseClassData), "baseCoverage"); 

var queryData = data.AsQueryable(); 

var left = Expression.Property(parm, "CoverageType"); 
var right = Expression.Constant(2m); 
var e1 = Expression.Equal(left, right); 

var whereMethod = Expression.Call(
    typeof(Queryable), 
    "Where", 
    new Type[] { queryData.ElementType }, 
    queryData.Expression, 
    Expression.Lambda<Func<BaseClassData, bool>>(e1, new ParameterExpression[] { parm })); 

Đây là những gì tôi đang sử dụng cho phương pháp chọn:

var selectParm = Expression.Property(parm, "LimitSelected"); 
    var selectMethod = Expression.Call(
     typeof(Enumerable), 
     "Select", 
     new Type[]{typeof(BaseClassData), typeof(decimal)}, 
     whereMethod, 
     Expression.Lambda<Func<BaseClassData, decimal>>(selectParm, new ParameterExpression[]{ parm}) 

     ); 

Khi tôi chạy đoạn code tôi nhận được lỗi này:

No generic method 'Select' on type 'System.Linq.Enumerable' is compatible with the supplied type arguments and arguments. No type arguments should be provided if the method is non-generic.

Tôi cũng đã thử thay đổi Enumerable thành Queryable và tôi nhận được cùng một lỗi.

+3

'Select' và' Where' take ** two ** generic parameters. – SLaks

+0

Bạn có nghĩa là trong mảng ParameterExpression? Tôi hỏi vì câu lệnh này hoạt động tốt như được mã hóa. Nếu tôi chỉ tạo truy vấn bằng phương thức where, mọi thứ sẽ hoạt động tốt. Đó là khi tôi cố gắng thêm phương thức chọn vào cây biểu thức. – MarkSalow

+0

Tôi đã thêm typeof (BaseClassData) vào mảng kiểu của selectMethod và nó hoạt động. – MarkSalow

Trả lời

-1

This might help with the error you describe above.

Bạn không cần phải tạo cho riêng mình tuy nhiên nơi/chọn, những người xây dựng vào C#/công việc LINQ tốt với các lớp học của riêng bạn:

void Main() 
{ 
    List<testdata> data = new List<testdata>(); 
    Directory.GetFiles(@"C:\").ToList().ForEach(x=>data.Add(new testdata(){file=x,returnable=1})); 
    data.Where(x=>x.file.Contains("g")).Select(x=>x.file).Dump(); 
} 

class testdata 
{ 
    public string file {get; set;} 
    public string returnable {get; set;} 
} 
3

Không cần phải sử dụng biểu .Call, bạn có thể trực tiếp xây dựng cây biểu hiện thay thế; Tôi đã tạo phương pháp tĩnh giúp tôi tạo truy vấn động:

public static void Test(string[] args) { 
    using (var db = new DBContext()) { 
    //query 1 
    var query1 = db.PrizeTypes.Where(m => m.rewards == 1000).Select(t => t.name); 

    //query 2 which equal to query 1 
    Expression<Func<PrizeType, bool>> predicate1 = m => m.rewards == 1000; 
    Expression<Func<PrizeType, string>> selector1 = t => t.name; 
    var query2 = db.PrizeTypes.Where(predicate1).Select(selector1); 
    Console.WriteLine(predicate1); 
    Console.WriteLine(selector1); 
    Console.WriteLine(); 

    //query 3 which equal to query 1 and 2 
    Expression<Func<PrizeType, bool>> predicate2 = GetPredicateEqual<PrizeType>("rewards", (Int16)1000); 
    Expression<Func<PrizeType, string>> selector2 = GetSelector<PrizeType, string>("name"); 
    var query3 = db.PrizeTypes.Where(predicate2).Select(selector2); 
    Console.WriteLine(predicate2); 
    Console.WriteLine(selector2); 

    //as you can see, query 1 will equal query 2 equal query 3 
    } 
} 

public static Expression<Func<TEntity, bool>> GetPredicateEqual<TEntity>(string fieldName, object fieldValue) where TEntity : class { 
    ParameterExpression m = Expression.Parameter(typeof(TEntity), "t"); 
    var p = m.Type.GetProperty(fieldName); 
    BinaryExpression body = Expression.Equal(
    Expression.Property(m, fieldName), 
    Expression.Constant(fieldValue, p.PropertyType) 
); 
    return Expression.Lambda<Func<TEntity, bool>>(body, m); 
} 

public static Expression<Func<T, TReturn>> GetSelector<T, TReturn>(string fieldName) 
    where T : class 
    where TReturn : class { 
    var t = typeof(TReturn); 
    ParameterExpression p = Expression.Parameter(typeof(T), "t"); 
    var body = Expression.Property(p, fieldName); 
    return Expression.Lambda<Func<T, TReturn>>(body, new ParameterExpression[] { p }); 
} 
+0

Cheeeeeers, maaaaate ... Tôi ước gì tôi đã tìm thấy điều này trước đó. Tôi sẽ tiết kiệm rất nhiều thời gian. Tôi vừa chép nó cho tôi. Ta! – Roman

Các vấn đề liên quan