2013-07-31 31 views
6

Tôi đang gặp một vấn đề tương tự đã được hỏi ở đây: LINQ to Entities does not recognize the method 'System.String ToString()' method, and this method cannot be translated into a store expressionLINQ to Entities không nhận ra phương pháp 'tên Phương pháp' phương pháp

Tôi đang cố gắng để đánh số trang nguồn của tôi, nhưng trong trường hợp của tôi, tôi có thể 't đặt kết quả của GetPropertyValue trong một biến, bởi vì tôi cần x để làm điều đó:

public IEnumerable<TModel> Paginate(IQueryable<TModel> source, ref int totalPages, int pageIndex, int pageSize, string sortfield, SortDirection? sortdir) 
{ 
    totalPages = (int)Math.Ceiling(source.Count()/(double)pageSize); 

    if (sortdir == SortDirection.Descending) 
    { 
     return source.OrderByDescending(x => GetPropertyValue(x, sortfield)).Skip(pageIndex * pageSize).Take(pageSize).ToList(); 
    } 
    else 
    { 
     return source.OrderBy(x => GetPropertyValue(x, sortfield)).Skip(pageIndex * pageSize).Take(pageSize).ToList(); 
    } 
} 

private static object GetPropertyValue(object obj, string name) 
{ 
    return obj == null ? null : obj.GetType().GetProperty(name).GetValue(obj, null); 
} 

tôi có thể làm gì trong trường hợp này?

+0

Bạn đang gặp phải vấn đề gì? Dường như bạn nhận được một không phải tất cả các đường dẫn trả về một giá trị? – Sayse

+0

Tôi nhận được "LINQ to Entities không nhận ra phương thức 'Phương thức tên phương thức', cụ thể hơn là phương thức" GetPropertyValue ". –

Trả lời

6

Biểu thức Lambda (Chúng được sử dụng trong trường hợp, OrderBy, v.v.) không thể chứa bất kỳ mã C# cụ thể nào, chúng chỉ có thể chứa cây biểu thức, được dịch sang SQL. Bạn không thể gọi bất kỳ phương thức tùy ý nào ở đó, ngoại trừ các phương thức được đề cập trong tài liệu EF như SqlFunctions, v.v.

Để sắp xếp với tên trường tại thời gian chạy, bạn phải tạo biểu thức lambda trong thời gian chạy và chuyển nó trên.

public IEnumerable<TModel> Paginate(IQueryable<TModel> source, ref int totalPages, int pageIndex, int pageSize, string sortfield, SortDirection? sortdir) 
{ 
    totalPages = (int)Math.Ceiling(source.Count()/(double)pageSize); 

    if (sortdir == SortDirection.Descending) 
    { 
     return source.OrderByDescending(sortfield).Skip(pageIndex * pageSize).Take(pageSize).ToList(); 
    } 
    else 
    { 
     return source.OrderBy(sortfield).Skip(pageIndex * pageSize).Take(pageSize).ToList(); 
    } 
} 


public static class QueryableHelper 
{ 
    public static IQueryable<TModel> OrderBy<TModel>(this IQueryable<TModel> q, string name) 
    { 
     Type entityType = typeof(TModel); 
     PropertyInfo p = entityType.GetProperty(name); 
     MethodInfo m = typeof(QueryableHelper).GetMethod("OrderByProperty").MakeGenericMethod(entityType, p.PropertyType); 
     return(IQueryable<TModel>) m.Invoke(null, new object[] { q, p }); 
    } 

    public static IQueryable<TModel> OrderByDescending<TModel>(this IQueryable<TModel> q, string name) 
    { 
     Type entityType = typeof(TModel); 
     PropertyInfo p = entityType.GetProperty(name); 
     MethodInfo m = typeof(QueryableHelper).GetMethod("OrderByPropertyDescending").MakeGenericMethod(entityType, p.PropertyType); 
     return (IQueryable<TModel>)m.Invoke(null, new object[] { q, p }); 
    } 

    public static IQueryable<TModel> OrderByPropertyDescending<TModel, TRet>(IQueryable<TModel> q, PropertyInfo p) 
    { 
     ParameterExpression pe = Expression.Parameter(typeof(TModel)); 
     Expression se = Expression.Convert(Expression.Property(pe, p), typeof(object)); 
     return q.OrderByDescending(Expression.Lambda<Func<TModel, TRet>>(se, pe)); 
    } 

    public static IQueryable<TModel> OrderByProperty<TModel, TRet>(IQueryable<TModel> q, PropertyInfo p) 
    { 
     ParameterExpression pe = Expression.Parameter(typeof(TModel)); 
     Expression se = Expression.Convert(Expression.Property(pe, p), typeof(object)); 
     return q.OrderBy(Expression.Lambda<Func<TModel, TRet>>(se, pe)); 
    } 
} 

Giải pháp này chỉ hoạt động ở cấp độ đơn nhất, nhưng bạn có thể xem SDK sau đây thực hiện tất cả những việc đó.

Tuy nhiên, nếu bạn xem xét bản thân Entity REST SDK, nó có nhiều thứ và tất cả những thứ bạn có thể cần. Disclaimer: Tôi là Tác giả.

https://entityrestsdk.codeplex.com

+0

Hầu như đã hoạt động. Bây giờ tôi nhận được một "Expression type" System.Int64 'không thể được sử dụng cho kiểu trả về' System.Object '". Tôi đã thay đổi 'Func >' thành 'Func >' và nó hoạt động, nhưng tôi không biết loại đối tượng sẽ được truyền cho hàm. Ví dụ: có thể là một chuỗi 'String'. Dù sao để giải quyết vấn đề này? –

+2

Bạn có thể thử ngay bây giờ không? Tôi đã sửa đổi nó ít. Tôi sẽ rời khỏi nhà trong ngày, nếu nó hoạt động tốt, nếu không tôi sẽ cố gắng đăng giải pháp, lớn hơn một chút, nhưng đó sẽ là ngày mai. –

+0

Tôi đã không, nhưng cảm ơn bạn rất nhiều vì đã giúp đỡ của bạn –

1

Thay vì sử dụng phản chiếu, bạn nên tạo động Expression<Func<TSource, TOrder>> và chuyển nó đến OrderBy.

Hãy xem here để hiểu cách tạo truy vấn động.