简体   繁体   中英

Would this perform better with LINQ?

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

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.

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).

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?

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM