2013-04-15 94 views
6

Tôi đang sử dụng mô hình đề cập ở đây http://www.asp.net/mvc/tutorials/getting-started-with-ef-using-mvc/implementing-the-repository-and-unit-of-work-patterns-in-an-asp-net-mvc-applicationđộng Func <IQueryable <TEntity>, IOrderedQueryable <TEntity>> Biểu hiện

Và tôi đang sử dụng phương pháp dưới đây để truy vấn EF

public virtual IEnumerable<TEntity> Get(
     Expression<Func<TEntity, bool>> filter = null, 
     Func<IQueryable<TEntity>, IOrderedQueryable<TEntity>> orderBy = null, 
     string includeProperties = "") 
    { 
     IQueryable<TEntity> query = dbSet; 

     if (filter != null) 
     { 
      query = query.Where(filter); 
     } 

     foreach (var includeProperty in includeProperties.Split 
      (new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries)) 
     { 
      query = query.Include(includeProperty); 
     } 

     if (orderBy != null) 
     { 
      return orderBy(query).ToList(); 
     } 
     else 
     { 
      return query.ToList(); 
     } 
    } 

Bây giờ tôi muốn tạo động Func<IQueryable<TEntity>, IOrderedQueryable<TEntity>> biểu thức để đặt hàng dữ liệu của tôi.

tôi biết tên trường chỉ như chuỗi và trật tự loại (tăng dần, giảm dần) là chuỗi (asc, desc)

+0

Đó không phải là hình thức thông thường cho một trật tự-do; bạn đã thấy cái này chưa? http://stackoverflow.com/questions/41244/dynamic-linq-orderby –

+0

@MarcGravell cảm ơn, tôi đã thấy điều đó. Nhưng hướng dẫn của MS chứa mã này vì vậy tôi đang cố gắng viết LINQ động phù hợp cho điều đó. Trên thực tế tôi nghĩ rằng tôi succeded nhưng tôi phải làm một số xét nghiệm và sau đó cho bạn biết. –

Trả lời

9

cuối cùng tôi có thể viết phương pháp tôi muốn.

public static Func<IQueryable<TEntity>, IOrderedQueryable<TEntity>> GetOrderBy(string orderColumn, string orderType) { 
      Type typeQueryable = typeof(IQueryable<TEntity>); 
      ParameterExpression argQueryable = Expression.Parameter(typeQueryable, "p"); 
      var outerExpression = Expression.Lambda(argQueryable, argQueryable); 
      string[] props = orderColumn.Split('.'); 
      IQueryable<TEntity> query = new List<TEntity>().AsQueryable<TEntity>(); 
      Type type = typeof(TEntity); 
      ParameterExpression arg = Expression.Parameter(type, "x"); 

      Expression expr = arg; 
      foreach(string prop in props) { 
       PropertyInfo pi = type.GetProperty(prop, BindingFlags.IgnoreCase | BindingFlags.Public | BindingFlags.Instance); 
       expr = Expression.Property(expr, pi); 
       type = pi.PropertyType; 
      } 
      LambdaExpression lambda = Expression.Lambda(expr, arg); 
      string methodName = orderType == "asc" ? "OrderBy" : "OrderByDescending"; 

      MethodCallExpression resultExp = 
       Expression.Call(typeof(Queryable), methodName, new Type[] { typeof(TEntity), type }, outerExpression.Body, Expression.Quote(lambda)); 
      var finalLambda = Expression.Lambda(resultExp, argQueryable); 
      return (Func<IQueryable<TEntity>, IOrderedQueryable<TEntity>>)finalLambda.Compile(); 
     } 

Phương pháp này có hai tham số, trước tiên một tên trường khác là tên là asc hoặc desc. Kết quả của phương thức có thể được sử dụng trực tiếp với đối tượng IQueryable.

Cám ơn bạn giúp

2

Tôi không chắc chắn chính xác những gì bạn muốn đạt được, nhưng tôi đã thay đổi mã của bạn và thêm một số ví dụ để chứng minh nó hoạt động như thế nào.

Đây là ứng dụng giao diện điều khiển đơn giản, có dummyText làm danh sách. Phương thức có thể truy vấn cho phép sử dụng biểu thức lọc và sắp xếp theo ý muốn. Tôi hy vọng nó sẽ giúp

class Program 
{ 

    private List<string> _dummyText = new List<string>(){ "Arda", 
     "Araba", 
     "Antartika", 
     "Balon"}; 

    static void Main(string[] args) 
    { 
     Program p = new Program(); 
     List<string> result = p.Get(s => s.StartsWith("A"), orderBy: q => q.OrderBy(d => d.Length)).ToList(); 

     Console.ReadLine(); 
    } 


    public virtual IEnumerable<string> Get(
    Expression<Func<string, bool>> filter = null, 
    Func<IQueryable<string>, IOrderedQueryable<string>> orderBy = null) 
    { 

     IQueryable<string> query = _dummyText.AsQueryable(); 

     if (filter != null) 
     { 
      query = query.Where(filter); 
     } 

     if (orderBy != null) 
     { 
      return orderBy(query).ToList(); 
     } 
     else 
     { 
      return query.ToList(); 
     } 



    } 

} 
+0

cảm ơn cho câu trả lời nhưng tôi nghĩ rằng có một số hiểu lầm. Tôi phải gửi z => z.OrderBy (x => x.CreatedDate) đến tham số orderBy. Vì vậy, câu trả lời của bạn sẽ không hoạt động theo ý kiến ​​của tôi. –

+0

Bạn có thể sử dụng một số tham số bên ngoài để biểu thức LINQ để thực thi phương thức có điều kiện dưới dạng nội dòng nếu ... Ví dụ: chuỗi trực tiếp = "DESC"; Danh sách result = p.Get (s => s.StartsWith ("A"), orderBy: q => ((trực tiếp == "ASC")? Q.OrderBy (d => d.Length): q. OrderByDescending (d => d.Length))). ToList(); Nhưng tôi cho rằng đây không phải là điều bạn muốn ... – Arda

1

này là rất muộn để dự buổi tiệc nhưng câu trả lời đúng tọa lạc trên một câu hỏi khác tại https://stackoverflow.com/a/10935223/14275

var students = repository.Get(x => x.FirstName = "Bob",q => q.OrderBy(s => s.LastName)); 
Các vấn đề liên quan