2014-11-02 28 views
0

我有房產和PropertyCompliance實體是這個樣子......重用表達式選擇單

public class Property{ 
    public virtual ICollection<PropertyCompliance> ComplianceRecords {get;set;} 
} 

public class PropertyCompliance{ 
    public virtual Property {get;set;} 
    public DateTime ComplianceDate {get;set;} 
    public ComplianceRating ComplianceValue {get;set;} //just an enum 
} 

在許多我需要找到PropertyCompliance最接近排至某一特定日期的地方。

var complianceRating = property.ComplianceRecords.OrderBy(cr=>cr.Date) 
    .Where(cr=>cr.ComplianceDate< checkDate).FirstOrDefault(); 

我知道我可以使用表達式作爲這樣的過濾ComplianceRecords:

var complianceRating = property.ComplianceRecords.Where(SomeExpression) 
    .OrderBy(cr=>cr.ComplianceDate).FirstOrDefault() 

然而,這是不是真的減少重複的量,因爲所有它做的是更換其中()語句。

有沒有辦法將表達式應用到屬性,以允許此過濾發生在另一個表達式中?喜歡的東西:

private static Expression<Func<Property, ComplianceRating>> PropertyComplianceForDate(DateTime checkDate) 
{ 
    return p => p.ComplianceRatings 
     .OrderByDescending(cr => cr.Date) 
     .First(cr => cr.Date <= checkDate).ComplianceRating; 
} 


public Expression<Func<Property, bool>> PropertyIsCompliant(DateTime checkDate) 
{ 
    return (p) => PropertyComplianceForDate(checkDate) == ComplianceRating.Compliant; 
} 

隨着「PropertyComplianceForDate」之處在於可以轉換爲SQL,以允許在SQL還使用了PropertyIsCompliant表達的表達。

+1

這應該可以在下一個版本的實體框架中使用。這個拉取請求昨天被實體框架接受,它實現了你所描述的內容:https://entityframework.codeplex.com/SourceControl/network/forks/BrandonDahler/EntityFramework/contribution/7352#!/tab/comments。基本上,這會檢查表達式中的方法在決定執行還是轉換爲sql之前返回表達式。如果你現在需要使用它,它應該可以在夜間生成:http://entityframework.codeplex.com/wikipage?title=Nightly%20Builds – rdans 2014-11-02 14:55:40

+0

你是否總是需要一個'Property'的記錄,或者你想要一個「屬性」列表中的所有這一個記錄(或沒有)加載在一個查詢?或者我們可以假設物業總是裝載所有'ComplianceRecords'? – 2014-11-02 22:17:16

+0

「PropertyIsCompliant」表達式將用於數據庫中屬性的列表。 var compliantProperties = db.Properties.Where(PropertyIsCompliant); – 2014-11-03 13:36:33

回答

1

您可以在類級別聲明一個表達式並重用它。

或者,你可以在你的表或擴展方法上做一個方法。擴展方法(在靜態類中)看起來像這樣:

public static PropertyCompliance PropertyIsCompliant(this IEnumerable<PropertyCompliance> complianceRecords, DateTime checkDate) { 
    return complianceRatings 
     .OrderByDescending(cr => cr.Date) 
     .First(cr => cr.Date <= checkDate); 
} 
+0

如果我使用上面的擴展方法,則在表達式中使用時將無法將其轉換爲SQL。我試過在Property類中有一個類似的方法,它和前面一樣,在另一個表達式中使用時不能轉換爲SQL。 – 2014-11-02 13:34:18

+0

你可以調用* tableName * .PropertyIsCompliant(date)或* query * .PropertyIsCompliant(date)。它應該轉換爲SQL。你試過了嗎? – 2014-11-02 13:37:08

+0

問題是我有PropertyIsCompliance表達式,如果它包含選擇正確的ComplianceRecord的邏輯,那麼這個表達式就沒有問題。我有其他表達式依賴於相同的日期選擇邏輯。所以我想要在1個地方。而不是在每個合規性表達式中重複。 – 2014-11-02 13:39:15