如果使用 LINQ,效果会更好吗?

发布于 2024-12-14 22:15:25 字数 738 浏览 1 评论 0原文

下面的方法选择管理员权限并从缓存的 DataTable 返回 bool,使用 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;
            }

Below method selects admin rights and returns bool from a cached DataTable, would it perform better with Linq?

You might ask why don't you test it. Well,due to lack of knowledge i can't write it in 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;
            }

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

初懵 2024-12-21 22:15:25

可能是这样。

让我们假设以下情况:

  1. 基础表的起始大小、读取频率和更新频率的平衡使得将整个表加载到内存中并只是重复查看来替换整个表是没有意义的。

  2. 每个 ID 仅有一个匹配行。

  3. 该行中有很多其他有趣的字段,我们在这里不关心。

然后,如果我们用 Linq2SQL Table 替换 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 Privileges WHEREprivilegeActionId=2

上面的 Linq 将转换为:

SELECT TOP 1 adminHasIt, moderatorHasIt FROM Privileges WHEREprivilegeActionId

您可以看到,如果这是一个包含很多内容的表列和/或如果有多个匹配行,这可能会更有效。

(如果 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;
}

它将要么只查询 adminHasIt,只查询 moderatorHasIt,要么根本不查询,因为我们保证 myRole 的任何其他值都为 false,无论什么数据库状态。

同样,您可以通过以下方式获得更简单的改进:

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。这种关于实际使用哪些数据的局部思考更容易做到,虽然大多数此类节省都很小,但有些节省很大(这个可能是),而且它们是一个习惯问题,而不是复杂的权衡问题。

It could be.

Let's assume the following:

  1. The balance of starting size, read frequency and update frequency of the underlying table is such that it doesn't make sense to replace the whole thing with loading it all into memory and just repeatedly looking at that.

  2. There's only one matching row for each id.

  3. There's a bunch of other interesting fields in the row, that we don't care about here.

Then if we replaced PrivilegeMap with a Linq2SQL Table<Privileges>, the equivalent LINQ code is going to be something like:

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;
}

(For that matter var result = PrivilegeMap.Where(p => p.PrivilegeActionId == actionID).First(p => new{p.ModeratorHasIt, p.AdminHasIt}) can also be written as var result = (from p in PrivilegeMap where p.PrivilegeActionId == actionID select new{p.ModeratorHasIt, p.AdminHasIt}).First() It's just a different syntax for the same LINQ operations).

Lets say actionID is 2
Your code will be turned into SQL along the lines of:

SELECT * FROM Privileges WHERE privilegeActionId=2

The Linq above would be turned into:

SELECT TOP 1 adminHasIt, moderatorHasIt FROM Privileges WHERE privilegeActionId

You can see how, if this were a table with lots of columns and/or if there was more than one matching row, this could be much more efficient.

(If PrivilegeMap was enumerable but not queryable it would turn into an operation where the whole thing was loaded and scanned, and hence not efficent at all).

On the other hand though, the code to produce that SQL could be more complicated, and it requires some work in setting up the privilege entity objects. If this were a one-off operation it certainly wouldn't be worth it in terms of either developer or runtime efficiency, but otherwise it could benefit both.

However, note that in both our cases we're querying needlessly. I'd actually replace mine with:

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;
}

Which will either query for just adminHasIt, just moderatorHasIt, or not query at all since we're guaranteed false for any other value of myRole no matter what the database state.

Likewise, you get a much simpler improvement with:

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"]);
}

Here we first avoid the database query entirely if we can't possibly use it, only convert the field we care about, and don't subsequently convert a bool to a bool. This sort of local thinking about what data is actually used is much easier to do and while most such savings are small, some are big (this one could potentially be) and they're a matter of habit rather than complicated trade-offs.

江南烟雨〆相思醉 2024-12-21 22:15:25

使用 LINQ 可能会更快,因为数据表不必解析查询字符串,但通过更改数据表示形式以避免首先查询数据表,您将获得最大的优势。

创建一个 IDictionary 来表示您感兴趣的权限,以 actionId 为键。然后当你需要查找时,你可以返回dict[actionId

无论如何,我怀疑这可能是一种“过早优化”的情况:您是否测试过您的程序并发现这段代码占了您处理时间的很大一部分?

It probably would be faster using LINQ because the datatable wouldn't have to parse your query string, but you'll get the greatest advantage by changing the data representation to avoid querying against a datatable in the first place.

Create an IDictionary<int, bool> that represents the privileges you're interested in, keyed by actionId. Then when you need to do a lookup, you can just return dict[actionId.

Regardless, I suspect this is probably a case of Premature Optimization: have you tested your program and found that this piece of code represents a significant portion of your processing time?

满身野味 2024-12-21 22:15:25

您列出的代码不完整,因为 myRole 变量未定义。

考虑到这一点,我建议将其写在 switch 语句中,然后继续,直到它被确定为问题为止。另外,它会更容易阅读(在我看来)。

The code you listed is not complete, as the myRole variable is not defined.

With that in mind, I would suggest writing it in a switch statement and move on till it is identified as a problem. Plus it would be easier to read (in my opinion).

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文