2011-11-10 29 views
1

下面的方法選擇管理員權限並從緩存的DataTable返回bool,它對Linq的性能會更好嗎?這對LINQ會更好嗎?

你可能會問爲什麼你不測試它。好了,由於缺乏知識,我可以把它寫在LINQ的

DataRow[] result = PrivilegeMap.Select("privilegeActionId=" + (int)actionId); 
      bool moderatorHasIt = Convert.ToBoolean(result[0]["moderatorHasIt"]); 
      bool adminHasIt = Convert.ToBoolean(result[0]["adminHasIt"]);           
      if (myRole == User.Role.Admin) 
      { 
       return Convert.ToBoolean(adminHasIt); 
      } 
      if (myRole == User.Role.Moderator) 
      { 
       return Convert.ToBoolean(moderatorHasIt); 
      } 
      else 
      { 
       return false; 
      } 
+0

我刪除了我的答案,因爲我記得DataTable基於'Select'查詢維護索引。 – Ani

回答

1

使用LINQ可能會更快,因爲數據表不必分析您的查詢字符串,但您將通過更改數據表示來獲得最大的優勢,以避免首先查詢數據表。

創建一個代表您感興趣的權限的IDictionary<int, bool>,鍵入actionId。那麼當你需要查詢時,你可以返回dict[actionId

無論如何,我懷疑這可能是過早優化的一種情況:您是否測試了您的程序並發現這段代碼代表了您處理時間的重要部分?

+0

謝謝,不,它只會被少數用戶調用。我只是想知道linq會不會有很大的區別 – nLL

+0

@nLL:那麼你的時間最好用在其他地方。 :-) – StriplingWarrior

+0

數據庫將不得不分析*東西*無論它來自Linq,Datatable還是手寫代碼SQL。 –

1

您列出的代碼是不完整的,因爲myRole變量沒有定義。

考慮到這一點,我建議將它寫入switch語句並繼續前進,直到它被識別爲問題。另外,它會更容易閱讀(在我看來)。

2

可能是。

假設如下:

  1. 起始大小,讀取頻率和基礎表的更新頻率的平衡是這樣的,它沒有任何意義與裝載所有到更換整個事情記憶,只是反覆看這個。

  2. 每個ID只有一個匹配的行。

  3. 行中還有一堆其他有趣的字段,我們不在乎這裏。

然後如果我們用LINQ2SQL Table<Privileges>取代PrivilegeMap,等效LINQ代碼將是這樣的:

var result = PrivilegeMap.Where(p => p.PrivilegeActionId == actionID).Select(p => new{p.ModeratorHasIt, p.AdminHasIt}).First() 
if (myRole == User.Role.Admin) 
{ 
    return result.AdminHasIt; 
} 
if (myRole == User.Role.Moderator) 
{ 
    return result.ModeratorHasIt; 
} 
else 
{ 
    return false; 
} 

(對於這個問題var result = PrivilegeMap.Where(p => p.PrivilegeActionId == actionID).First(p => new{p.ModeratorHasIt, p.AdminHasIt})也可以寫爲var result = (from p in PrivilegeMap where p.PrivilegeActionId == actionID select new{p.ModeratorHasIt, p.AdminHasIt}).First()這只是一個不同相同的LINQ操作的語法)。

比方說actionID2 您的代碼將沿着線變成SQL:

SELECT * FROM特權WHERE privilegeActionId = 2

以上的Linq就會變成:

SELECT TOP 1 adminHasIt,moderatorHasIt FROM Privileges WHERE privilegeActionId

你可以看到,如果這是一個有很多列和/或如果有多個匹配的行,這可能會更有效率。

(如果PrivilegeMap是可枚舉的但不可查詢,它將變成一個操作,其中整個事物被加載和掃描,因此根本沒有效率)。

另一方面,雖然產生該SQL的代碼可能更復雜,並且它需要一些工作來設置特權實體對象。如果這是一次性操作,無論是開發人員還是運行時效率,這當然都不值得,但否則它可能會同時受益。

但是,請注意,在我們的兩種情況下,我們都在不必要地查詢。其實我與賠償我:

if (myRole == User.Role.Admin) 
{ 
    return PrivilegeMap.Where(p => p.PrivilegeActionId == actionID).Select(p => p.AdminHasIt).First(); 
} 
if (myRole == User.Role.Moderator) 
{ 
    return PrivilegeMap.Where(p => p.PrivilegeActionId == actionID).Select(p => p.ModeratorHasIt); 
} 
else 
{ 
    return false; 
} 

這將因爲我們爲myRole任何其他值保證假不管是什麼數據庫狀態只是adminHasIt,只是moderatorHasIt,或無論是查詢不是在所有查詢

同樣地,你會得到一個更簡單的改進:

if(myRole != User.Role.Admin && myRole != User.Role.Moderator) 
    return false; 
DataRow[] result = PrivilegeMap.Select("privilegeActionId=" + (int)actionId); 
if (myRole == User.Role.Admin) 
{ 
    return Convert.ToBoolean(result[0]["adminHasIt"]); 
} 
if (myRole == User.Role.Moderator) 
{ 
    return Convert.ToBoolean(result[0]["moderatorHasIt"]); 
} 

在這裏,我們首先避免數據庫查詢完全如果我們不可能使用它,只轉換我們關心的領域,不隨後將bool轉換爲bool。這種關於實際使用數據的地方性思維要容易得多,儘管大多數這種節省很少,但有些很大(這可能是潛在的),而且這是習慣問題,而不是複雜的折衷。

+0

感謝您的詳細解釋。現在更清楚了。 – nLL

+0

不客氣,儘管我現在只看到你的問題說表已被緩存。在這種情況下,用@StriplingWarrior製作的建議可以更快地使用字典。也就是說,你當然可以查詢同一張表(無論是緩存的DataTable還是用於Linq2Objects的List ),以便再次改變餘額。在後一種情況下,linq和你的方法之間的表現更接近。 –

+0

+1非常棒的答案。 – StriplingWarrior

相關問題