2017-08-24 57 views
1

我是實體框架和linq的新手。我正在使用asp.net mvc 5和C#。 我寫的動態排序查詢,如下所示:實體框架linq orderby函數

public static IEnumerable<T> OrderByDynamic<T>(this IEnumerable<T> source, string propertyName, bool Ascending) 
{ 
    if (Ascending) 
     return source.OrderBy(x => x.GetType().GetProperty(propertyName).GetValue(x, null)); 
    else 
     return source.OrderByDescending(x => x.GetType().GetProperty(propertyName).GetValue(x, null)); 
    } 

,並在我的倉庫,我可以寫:

string sortExpr = "name"; 
_objDB.hotels.Where(s => (s.city_id = 1)) 
      .OrderByDynamic(sortExpr, Ascending).ToList(); 

此代碼工作正常排序是在一個表中的列時,但我需要通過SQL函數進行排序。我進入功能到.edmx模型下面的代碼

[EdmFunction("hotelReservation.Core.Data", "getHotelMinPrice_cap")] 
public static int getHotelMinPrice_cap(int Hotel_id, int capacity, DateTime enter_date, DateTime exit_date) 
{ 
    throw new NotSupportedException("Direct calls are not supported."); 
} 

和我的SQL的選擇是一樣的東西:

select * 
from hotel 
where city_id = 1 
order by dbo.getHotelMinPrice_cap(hotel.id,1,'2001-01-01', '2021-01-01') 

我怎麼能寫在LINQ動態排序的最後一個SQL查詢?

+0

爲了用一個函數是一個不好的做法。您應該首先優化您的查詢。提供你的函數'getHotelMinPrice_cap',以便提供優化方式。 –

+0

SELECT MIN(room_price.price) 從room_price,room_definition 其中room_price.roomDef_id = room_definition.ID 和room_definition.Hotel_id = HOTEL_ID和room_definition.capacity =容量 之間enter_date和exit_date或room_price.stop_date之間(room_price.start_date enter_date和exit_date) – saeedeh

+0

我正在詢問sql函數。 –

回答

0

由於哈拉爾Coppoolse的答案 我終於做到了這樣:

_objDB.hotels .Select(h=> new { id= h.id, name=h.name, star=h.star, 
        minPrice1 = hotel.getHotelMinPrice_cap(h.id, 1, model.date_check_in, model.date_check_out)}) 
.Where(s => (s.city_id = 1)) 
.OrderByDynamic(sortExpr, Ascending).ToList(); 

在這種情況下,我可以選擇sortExpr = minPrice1;,它將由SQL函數來排序。

我也改變了OrderByDynamic功能波紋管:

public static IQueryable<T> OrderByDynamic<T>(this IQueryable<T> q, string SortField, bool Ascending) 
     { 
      var param = Expression.Parameter(typeof(T), "p"); 
      var prop = Expression.Property(param, SortField); 
      var exp = Expression.Lambda(prop, param); 
      string method = Ascending ? "OrderBy" : "OrderByDescending"; 
      Type[] types = new Type[] { q.ElementType, exp.Body.Type }; 
      var mce = Expression.Call(typeof(Queryable), method, types, q.Expression, exp); 
      return q.Provider.CreateQuery<T>(mce); 
     } 

我網頁上找到: https://stackoverflow.com/a/7265354/8509940

1

您的解決方案引入了幾個問題:

  • OrderBy通過名稱的屬性,希望您訂購的對象具有這種性質。如果你的對象沒有這個屬性呢?
  • SQL不理解像GetProperty()這樣的函數,所以這個排序必須在本地內存(AsEnumerable)中完成,而不是更快的SQL服務器(AsQueryable)。
  • 您可以使用存儲過程進行排序。

    public static IEnumerable<T, TKey> OrderByDynamic<T>(this IEnumerable<T> source, 
        Func<T, TKey> keySelector, System.ComponentModel.ListSortDirection sortDirection) 
    { 
        if (sortDirection == ListSortDirection.Ascending) 
         return source.OrderBy(keySelector); 
        else 
         return source.OrderByDescending(keySelector); 
    } 
    

    用法是這樣的::

前兩個問題可以很容易地通過一個Func<TSource, TKey> keySelector改變參數propertyName來解決

var result = Students.OrderByDynamis(student => student.Name, ListSortDirection.Ascending); 

這種方法的好處是,你的如果您嘗試通過不存在的屬性進行排序,編譯器會發出抱怨。此外OrderBy可以執行AsQueryable;它可以由您的數據庫執行,而不是在本地內存中執行。

使用字符串來選擇您想要的屬性是一個壞主意。

如果您輸入錯誤,您只能在運行時檢測到此錯誤。此外:如果您知道在編寫代碼的過程中需要輸入的字符串爲propertyName,您還知道要分類的對象類型,因此您可以改爲編寫keySelector

你的第二個問題是調用存儲過程作爲排序順序。這是比較容易解決的,如果你首先調用的返回值的存儲過程,然後順序:

var result = Hotels.Where(hotel => hotel...) 
    .Select(hotel => new 
    { 
     StoredProcedureValue = CallStoredprocedure(hotel,...), 
     Hotel = hotel, 
    }) 
    .AsEnumerable() // bring the result to local memory 
    .Orderby(item => item.StoredProcedureValue) 
    .Select(item => item.Hotel); 

只有酒店,將在您的最終結果傳送到本地內存,搭配的結果一起存儲過程。他們只被要求在最終結果中使用的酒店。

但是,排序是在本地內存中完成的。如果您還希望在數據庫端完成此排序,則必須創建一個新的存儲過程,在執行排序之前調用其他存儲過程。

+0

非常感謝您的答案。我不知道你寫的'StoredProcedureValue'和'CallStoredprocedure'是什麼!他們是什麼?我想使用一個名爲'getHotelMinPrice_cap'的函數 – saeedeh

+0

看來你對匿名類型並不熟悉。在Where語句中,我從Collection中的每個項目收集'Hotels',並使用標識符'hotel'方便地識別,我創建了一個匿名類的新對象,具有兩個屬性:'StoredProcedureValue'和' Hotel'。我不知道你是如何得到存儲過程的價值的,所以我只是調用一個可以像你平常那樣做的函數。 Orderby以匿名類型作爲輸入 http://geekswithblogs.net/BlackRabbitCoder/archive/2012/06/21/c.net-little-wonders-the-joy-of-anonymous-types.aspx –