2011-11-10 32 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

相关问题