2013-02-15 42 views
3

任何人都可以請建議我,有沒有更好的方法寫下面的代碼使用開關盒或任何(謝謝大家在這裏給你的寶貴建議我在Linq查詢中使用它,我觀察到一些修改它包含不同的產品名稱)寫一個開關盒

from p in l_list 
    where ((LicenceType == "Full" && SystemType == "Single") && p.ProductName != "Full DoubleProduct ") 
     || ((LicenceType == "Full" && SystemType == "Multiple") && p.ProductName != "Full SingleProduct") 
     || ((LicenceType == "Partial" && SystemType == "Single") && p.ProductName != "Locked DoubleProduct") 
     || ((LicenceType == "Partial" && SystemSize == "Multiple") && p.ProductName != "Locked SingleProduct") 
     || ((LicenceType == "Locked" && SystemSize == "Single") && p.ProductName != "Locked DoubleProduct") 
     || ((LicenceType == "Locked" && SystemType == "Multiple") && p.ProductName != "Locked SingleProduct") 
+3

您標記了C#,但是關鍵字'where'對於C#無效...... – luiges90 2013-02-15 13:12:53

+5

@ luiges90 - 它看起來像查詢表達式的一部分。 – Lee 2013-02-15 13:13:44

+0

看到這是在Linq聲明中使用,請讓我們知道哪個提供者正在使用(即linq到objects/linq到ef/linq到sql) – spender 2013-02-15 13:13:53

回答

6

那滔天的布爾條件描述你的數據對象的子集之間共享一些共同的品質。指出質量並給它一個描述性的名稱。

然後,通過數據對象的屬性公開該數量的值,或者寫一個相同的擴展方法。最後,使用此訪問器替換現有條件。

例如,如果質量的名稱是「友好」,那麼你可以這樣做:

where model.IsFriendly // property 

或本:

where model.IsFriendly() // extension method BusinessRules.IsFriendly(Model m) 
+1

如果將表達式轉換爲SQL,可能會非常棘手,但創建條件的抽象似乎是一種好方法。 +1 – spender 2013-02-15 13:21:48

0

您可以使用標誌來表明什麼值的對象或一個屬性。

[Flags] 
enum MyEnum 
{ 
    val1 = 0x01, 
    val2 = 0x02, 
    val3 = 0x04 
} 

可以使用按位運算符(& &,||)檢查的價值。見here

4

它看起來像您可以簡化表達「分解出」的許可證類型,並觀察該條件歸結爲一個簡單得多的

(
(SystemType == "Single" && p.ProductName != "DoubleProduct") || 
(SystemType == "Multiple" && p.ProductName != "SingleProduct") 
) && 
(
LicenceType == "Full" || 
LicenceType == "Partial" || 
LicenceType == "NotApplicable" 
) 

如果有比"Full"其他沒有牌照類型,"Partial""NotApplicable",你可以扔掉第二子句的

(SystemType == "Single" && p.ProductName != "DoubleProduct") || 
(SystemType == "Multiple" && p.ProductName != "SingleProduct") 

編輯的最終條件:在一般情況下,當你有複雜多重峯像這樣的最終部分條件,您可以做的最好的辦法是提取常見的子表達式,並嘗試減少條件數量。根本的問題是,你試圖在代碼中表達「線性」的多維度條件;這種「摺疊」會導致難以閱讀的代碼。解決此問題

一種方式是「編碼」,在表中你的狀態,就像這樣:

var conditions = new[] { 
    new[] { "Full",   "Single", "Full DoubleProduct" } 
, new[] { "Full",   "Multiple", "Full SingleProduct" } 
, new[] { "Partial",  "Single", "Locked DoubleProduct" } 
, new[] { "Partial",  "Multiple", "Locked SingleProduct" } 
, new[] { "NotApplicable", "Single", "Locked DoubleProduct" } 
, new[] { "NotApplicable", "Multiple", "Locked SingleProduct" } 
}; 

現在你可以使用它的條件是這樣的:

Where (p => conditions.Any(cond => 
    cond[0] == p.LicenceType 
&& cond[1] == p.SystemType 
&& cond[2] != p.ProductName 
)) 

的優勢這種方法是條件爲您的程序的讀者「列表」,並且可以通過簡單地添加新行來輕鬆擴展。缺點是,您不能再針對IQueryable源運行類似的查詢,而不會將部分結果帶入內存。

+0

Hi @ dasblinkenlight,感謝您的回覆。在這裏我有不同的產品名稱。我通過看到如果你可以請引導我 – Kittu 2013-02-15 13:59:46

+0

編輯我的問題它並不總是與產品名稱比較,但可以比較ChildProductName – 2013-02-15 14:08:40

+0

對不起,它是我的錯誤,只有產品名稱沒有ChildProductName.I已重新編輯我的問題。 – Kittu 2013-02-15 14:27:00

0

您可以將條件「編碼」爲數組(狀態矩陣),然後使用foreach/for和flags。

另一個可能的解決方案是由bash.d已經使用的位域。如果你真的需要,你可以進一步結合

我自己避免使用重複的字符串(比如「Full」),而是將它們放在常量中以避免出錯和更好的可讀性(有時)。

當操作數具有相同的優先級時,您也不需要使用括號,例如,(a == b && c == d) && e == f不需要配置。

最後但並非最不重要的是,您可以嘗試反轉邏輯,這可能會簡化條件,例如,(a || b || c) = !(!a && !b && !c)。如果您正在處理可能條件的已知子集,那麼這可能特別有用,然後您可以「優化」它。

0

在Linq中,您可以調用外部函數。 那麼爲什麼你不把「業務邏輯」移出查詢呢? 也就是說你可以創建一個方法

bool IsLincensedForXXX(Product p) 

,並在LINQ表達式中使用它:

from p in l_list where IsLincensedForXXX(p) 

我認爲這是更清潔,更容易十個分量和重用。

+0

Hi @Stefano Altieri,這也是我正在尋求單獨編寫一個函數。但是我怎麼能根據以上三個條件過濾(LicenceType,SystemSize,ProductName)。請指導我 – Kittu 2013-02-15 15:24:34

+0

是LicencyTpe。 SystemSize,...產品屬性? – 2013-02-15 15:40:20

+0

是LicenceType和SystemSize是屬性 – Kittu 2013-02-15 15:50:00