2016-06-10 53 views
3

我有2個實體框架查詢幾乎相同,除了2個屬性的lambda外; Select()方法中的位置和日期時間。是否有可能將Linq中的lambda參數化爲實體選擇

我試圖創建一個擴展方法,分享其沒有FUNC PARAM作品的選擇,但它拋出一個異常,那麼我使用的位置PARAM:

public static IQueryable<DashboardItem> SelectDashboardItem(this IQueryable<Job> query, 
      string direction, 
      Func<Job, MeetingDetail> location) 
    { 
     return query 
      .Select(j => new DashboardItem() 
      { 
       JobId = j.Id, 
       Direction = direction, 
       CustomerName = j.Driver.Name, 
       Vehicle = j.Vehicle, 
       // This works without using the func 
       Location = location(j).MeetingLocation.Name, 
       DateTime = location(j).DateTime,      
      }); 
    } 

我看到他的錯誤信息:

LINQ to Entities不支持LINQ表達式節點類型'Invoke'。

回答

1

在let語句中使用此語法可以在一舉中實現組合。您需要一個基類,或者更好的界面,以便您的出發和退貨實體之間的通用性。

var query = from job in _dataContext.Job 
    let departureOrReturn = (direction == "PickUp" ? job.Departure : job.Return) as BaseReturnOrDeparture 
    where (departureOrReturn.DateTime >= startDate && departureOrReturn.DateTime <= endDate) 
    select new DispatchDashboardItem 
    { 
     JobId = job.Id, 
     Direction = direction, 
     CustomerName = job.Driver.Name, 
     Vehicle = job.Vehicle, 
     Location = deptartureOrReturn.MeetingLocation.Name, 
     DateTime = deptartureOrReturn.DateTime, 
    }; 
+1

不好意思,也許我冗長的問題造成了混淆,在.Select方法中' Location'和'DateTime'需要根據方向使用'j.Return'或'j.Departure',因此我試圖將它移動到一個擴展方法 –

+0

檢查最後一個編輯和第二個語法。沒有一個編譯器方便,但類似的東西是一個更簡單的方法來實現這一點。 –

+0

爲什麼這是downvoted? –

0

代替使用作爲Func參數使用Expression .Pass要用作參數的同lambda表達式的,它會隱式轉換。現在,實現你需要什麼,你需要使用LinqKit庫:

public static IQueryable<DashboardItem> SelectDashboardItem(this IQueryable<Job> query, 
      string direction, 
      Expression<Func<Job, MeetingDetail>> location) 
    { 
     return query.AsExpandable() 
     .Select(j => new DashboardItem() 
     { 
      JobId = j.Id, 
      Direction = direction, 
      CustomerName = j.Driver.Name, 
      Vehicle = j.Vehicle, 
      // This works without using the func 
      Location = location.Invoke(j).MeetingLocation.Name, 
      DateTime = location.Invoke(j).DateTime,      
     }); 
    } 

Explanation:

ToExpandable周圍產生DLINQ表對象的簡單封裝。多虧了這個包裝器,你可以使用第二種方法Invoke來擴展Expression類來調用lambda表達式,同時還可以將查詢轉換爲T-SQL。這是有效的,因爲當轉換爲表達式樹時,包裝器會用調用的lambda表達式的表達式樹替換所有出現的Invoke方法,並將這些表達式傳遞給能夠將展開後的查詢轉換爲T-SQL的DLINQ。

+0

那麼如何使用param? 'location(j).MeetingLocation.Name'或'location.MeetingLocation.Name'無效 –

+0

@jimmy_b,我已更新我的回答 – octavioccl

+0

Invoke()返回一個System.Linq.Expressions.Expression而不是func的對象 –

相關問題