Самым простым подходом IMO будет разделение функций по наборам страниц, которые используют безопасность для определения того, какую страницу получает пользователь. Помимо безопасности и других средств, гарантирующих, что пользователь не сможет получить доступ к странице, к которой у него нет прямого доступа (карты сайта и т. Д.), Вы можете сохранить в базе данных список функций, а также то, какие пользователи или роли имеют доступ к этой функции:
Create Table Features
(
Code varchar(10) not null Primary Key
, StartPage nvarchar(max) not null
, Description nvarchar(max) not null
)
Create Table UserFeatures
(
UserId ... not null
, FeatureCode varchar(10) References Features ( Code )
)
Во-первых, причина, по которой я бы использовал текстовый код для первичного ключа функции, а не суррогатный ключ, такой как столбец IDENTITY или guid, заключается в том, что только система будет запрашивать функции. Пользователи никогда не смогут произвольно добавить функцию. Таким образом, он делает ваш код намного чище и проще для чтения для запроса ...Where FeatureCode = 'AdvancedEntry'
, чем ...Where FeatureId = 13
.
Во-вторых, при таком подходе код самих страниц будет определять, какую процедуру вызывать. Однако это может означать некоторое дублирование, если функции просто включают дополнительные поля информации.
Таким образом, если функции тесно интегрированы в существующую кодовую базу и уровень представления (что, кстати, является причиной того, что управление версиями так сложно), альтернативным подходом будет сохранение имени хранимой процедуры, которая должна использоваться в Features
таблица Ваш код запросит присоединение к вышеуказанным таблицам и вернет имя хранимой процедуры, которое следует использовать. Для аргументов вы можете сохранить параметризованный вызов в базе данных (например, exec Schema.Foo @bar, @gamma, @beta
), и при выполнении запроса просто проверить, содержит ли эта строка заданный параметр, и, если это так, добавить значение этого параметра:
if ( ProcTemplate.Contains( "@bar")
commandInstance.Parameters.AddWithValue( "@bar", barValue );
if ( ProcTemplate.Contains( "@gamma")
commandInstance.Parameters.AddWithValue( "@gamma", gammaValue );
...
Если вы сопоставляете объекты с ролями или группами пользователей, вам нужно будет разработать «превентивные» правила, определяющие, какой объект следует использовать в случае возвращения нескольких объектов. При таком подходе вы бы оставили существующие хранимые процедуры без изменений в схеме, которые требовали изменения хранимой процедуры (например, удаление столбца). Бонусным результатом этого подхода является то, что вы можете добавить дату в таблицу Features
, чтобы определить, когда новая функция должна появиться в сети.