Будет ли это работать лучше с LINQ? - PullRequest
1 голос
/ 10 ноября 2011

Приведенный ниже метод выбирает права администратора и возвращает 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;
            }

Ответы [ 3 ]

2 голосов
/ 11 ноября 2011

Это может быть.

Предположим следующее:

  1. Баланс начального размера, частоты чтения и частоты обновления базовогоТаблица такова, что нет смысла заменять все это загрузкой всего в память и просто неоднократно смотреть на это.

  2. Для каждого идентификатора есть только одна подходящая строка.

  3. Есть ряд других интересных полей в строке, которые нас не волнуют.

Тогда, если мы заменили PrivilegeMap наLinq2SQL Table<Privileges>, эквивалентный код 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).

Допустим, actionID - это 2 Ваш код будет преобразован в 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;
}

, который будет либо запрашивать только adminHasIt, просто moderatorHasIt, либо вообще не запрашивать, поскольку мы гарантируем false для любого другого значения myRoleнезависимо от того, в каком состоянии находится база данных .

Аналогичным образом, вы получаете гораздо более простое улучшение:

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.Такого рода локальные размышления о том, какие данные на самом деле используются, гораздо проще сделать, и, хотя большинство таких сбережений невелики, некоторые из них велики (это может быть), и это скорее привычка, чем сложные компромиссы.

1 голос
/ 10 ноября 2011

Вероятно, было бы быстрее использовать LINQ, потому что таблица данных не должна была бы анализировать строку запроса, но вы получите наибольшее преимущество, изменив представление данных, чтобы избежать запросов к базе данных.

Создайте IDictionary<int, bool>, представляющий интересующие вас привилегии, с ключом actionId. Тогда, когда вам нужно сделать поиск, вы можете просто вернуть dict[actionId.

Несмотря на это, я подозреваю, что это, вероятно, случай Преждевременная оптимизация : вы тестировали свою программу и обнаружили, что этот фрагмент кода представляет значительную часть вашего времени обработки?

1 голос
/ 10 ноября 2011

Указанный вами код не является полным, поскольку переменная myRole не определена.

Имея это в виду, я бы предложил написать это в операторе switch и двигаться дальше, пока он не будет определен как проблема. Плюс было бы легче читать (на мой взгляд).

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...