Многопользовательское приложение, совместно использующее данные (Asp net mvc + Entity Framework + Sql Server)

Я разрабатываю довольно сложную архитектуру приложения с несколькими арендаторами.

.

3 совершенно разных приложения

Это не только один тип приложений, используемых многими клиентами; Есть 3 различных типа приложений.

ПРИЛОЖЕНИЕ A, ПРИЛОЖЕНИЕ B, ПРИЛОЖЕНИЕ C

.

Каждое приложение является мультитенантным

У каждого приложения есть свои клиенты.

ПРИЛОЖЕНИЕ A - клиент A1 - клиент A2

ПРИЛОЖЕНИЕ B - клиент B1 - клиент B2

ПРИЛОЖЕНИЕ C - клиент C1 - клиент C2

.

ОБЩАЯ ИНФОРМАЦИЯ

Многие приложения передаются разными приложениями.

"клиент A1" должен управлять или просматривать только данные, принадлежащие "клиенту C1".

.

ВОПРОС

Учтите, что я использую Asp net mvc, EF, Sql Server. Какая реализация правильная?

Один сайт и много областей? Создать несколько сайтов? Несколько db? Только один дб? Фильтрация? Просмотр с фильтром sql? ...

Пример приложения?

РЕДАКТИРОВАТЬ

и ... Куда девать бизнес-логику?


person Marco Staffoli    schedule 12.11.2010    source источник


Ответы (5)


Я бы порекомендовал вам сначала создать свой собственный многопользовательский инженерный стек (Framework) поверх .Net, который будет обрабатывать все требования мультитенантности с точки зрения изоляции данных для клиентов, поддержки горизонтального масштабирования, фильтрации представлений на основе контекст клиента и роль пользователя, расширение модели данных для клиента, настройка пользовательского интерфейса для клиента, применение ограничений доступа на основе ролей, привилегий и области данных, которые могут быть разными для разных клиентов и т. д.

Бизнес-логика может быть построена поверх этой структуры. Такой подход обеспечит вашему продукту прочный инженерный фундамент.

Другой вариант - купить готовый к использованию многопользовательский инженерный стек с полки, установить его в Visual Studio и использовать в качестве шаблона разработки.

person Ramkumar    schedule 21.01.2011

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

Но в любом случае вы должны убедиться, что ВСЕ функции базы данных используют правильное соединение с базой данных или ключ столбца клиента. Это настоящая проблема

Чтобы убедиться в этом, используйте только ОДНУ функцию для каждого приложения, которое принимает это решение, и убедитесь, что все функции базы данных не работают, если они не вызвали эту функцию (прямо или косвенно, как показано ниже).

например С помощью MVC в функции global.asax AuthenticateRequest или BeginRequest вы можете проверить, кем является пользователь, а затем вычислить, какое соединение с базой данных им нужно использовать или какой ключ столбца клиента они должны использовать в КАЖДОМ запросе для этого запроса. Затем это сохраняется в переменной сеанса и т. Д.

Если у вас три приложения, я бы сделал три отдельных сайта. Они могут использовать общие классы через общий проект. Жизнь в целом проще, если их можно развернуть отдельно

person TFD    schedule 01.12.2010
comment
Согласитесь с важностью сохранения изоляции арендаторов с помощью одиночных шлюзов. Не согласны с тем, что физически разные базы данных для каждого арендатора - идеальное решение. С точки зрения масштаба POV, как правило, нецелесообразно иметь отдельные базы данных для мультитенантных приложений, у которых есть тысячи или миллионы клиентов. Один или один набор БД необходим, чтобы БД могла быть распределена или кластеризована. Множественные точки входа в кластерные среды - это анархия. - person Matt Kocaj; 01.12.2010
comment
@cottsak Все зависит от предполагаемого назначения данных, масштаба и т. д. вашего приложения. Не многие люди имеют дело с тысячами или миллионами арендаторов или даже с кластерами. Где твой ответ? - person TFD; 05.12.2010
comment
@TFD Не думал, что это ответ. Только мое мнение. - person Matt Kocaj; 06.12.2010
comment
физически разные базы данных для каждого арендатора - плохое решение этой проблемы, потому что каждый арендатор должен делиться данными с другими двумя типами арендаторов. - person Marco Staffoli; 06.12.2010
comment
@Bugeo Как это проблема? Одно приложение может читать любое количество источников данных. Не говорю, что это лучший ответ, поскольку я не знаю вашего количества клиентов или размера БД, но это очень чистый метод. - person TFD; 07.12.2010
comment
@TFD проблема не читается из другого источника данных. Проблема в обмене. Другая проблема заключается в запросе таких же данных из многопозиционного источника данных. Предположим, что App-A1 необходимо прочитать весь заказ из App-B1, AppB2 ... AppB200. это означает 200 запросов из 200 разных источников данных ... - person Marco Staffoli; 07.12.2010
comment
@Bugeo Это не будет проблемой. Уровню службы данных просто нужен ключ, чтобы определить, какой источник данных (по ключу или соединению) использовать. Фактически все они имеют одинаковую стоимость доступа. Проблема с мультитенантностью состоит в том, чтобы гарантировать, что ВСЕ ваш код каждый раз обращается к правильному источнику данных, и что вы не можете случайно написать функцию, которая обходит это. Для обмена данными вам нужна дополнительная функция, которая проверяет авторизацию для другого источника данных и возвращает ключ или соединение для использования вместо значения по умолчанию для этого клиента. - person TFD; 08.12.2010

Это конкретный ответ, но это лишь некоторые аспекты, которые вы можете учесть при его разработке.

Что касается общей информации, я думаю, что наиболее важной частью здесь является определение отношений между клиентами, а также ролей и прав, которые каждый клиент имеет по отношению к другим клиентам. Лучше всего начать с определения того, что именно можно сделать.

Пример:

Read Only|cust1|cust2|cust3
---------+-----+-----+-----
customer1| 1   | 1   | 0
customer2| 0   | 1   | 0
customer3| 1   | 0   | 1

Write    |cust1|cust2|cust3
---------+-----+-----+-----
customer1| 1   | 1   | 0
customer2| 0   | 1   | 0
customer3| 0   | 0   | 1

Итак, в приведенном выше примере customer1 может читать и записывать (обновлять) данные customer2.

При этом основная проблема заключается в моделировании этих отношений, то есть общей информации. Используя предложение @ TFD, эти отношения могут быть загружены в сеанс, когда клиент входит в систему вместе с соответствующими идентификаторами клиента.

(Основываясь на предоставленной информации, я также склоняюсь к тому, что это может быть проблема отдельного приложения, а не только клиента. Чтобы проиллюстрировать это, замените значения «cust» в приведенных выше таблицах на App.)

Создавайте отдельные сайты для каждого приложения, поскольку я предполагаю, что каждое приложение имеет уникальную цель, хотя есть общие функции.

Возможно, потребуется другая база данных конфигурации, если есть другие взаимосвязи между данными. БД будет хранить всю информацию о клиенте (включая отношения с другими приложениями) для каждого приложения. Причина этого предложения заключается в том, что, как я вижу, у вас есть три отдельных мультитенантных приложения, независимых друг от друга, с использованием подхода с общей базой данных, но каждое приложение должно взаимодействовать с другим приложением на каком-то уровне.
С точки зрения клиентов в БД, я бы предложил ограничить таблицу «Клиенты» конфигурационной БД. Затем вы можете иметь базу данных контента, основанную на требованиях каждого приложения.

person Ahmad    schedule 01.12.2010

Я предлагаю использовать PRISM с шаблоном дизайна Sliverlight и MVVM. PRISM разработан для такого типа составного приложения, где каждое приложение является независимым и может также взаимодействовать друг с другом через события, предоставляемые PRISM.

person TheITGuy    schedule 20.01.2011

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

Один из способов сделать это - убедиться, что существуют хранимые процедуры для доступа к любым таблицам, а логика безопасности встроена в хранимые процедуры. Вы можете гарантировать, что для каждого клиента используется другое имя пользователя db и что это имя пользователя db сопоставляется с этим идентификатором клиента в таблице сопоставления. Затем сохраненные процедуры всегда могут иметь проверку, что запрашиваемые / изменяемые данные действительно принадлежат идентификатору клиента, сопоставленному с пользователем базы данных, который запускает процесс (с использованием контекстной информации).

Затем вам понадобится способ убедиться, что соединение с базой данных, созданное приложением, использует только соответствующее имя пользователя, которое сопоставляется с этим идентификатором клиента. Это означает, что вам нужен еще один хранимый процесс, который предоставляет вам эту информацию (возможно, с именем пользователя / идентификатором в качестве входных данных), и этот хранимый процесс должен выполняться через общее имя пользователя db. Помните, что это единственная хранимая процедура, которая должна иметь привилегии выполнения, предоставленные этому обычному пользователю базы данных.

Это может выглядеть как написание кучи дополнительного кода, но это действительно помогает знать, что ваша база данных будет отклонять неверные запросы даже из-за ошибок приложения. Единственное место, где вы должны быть действительно, очень осторожны, - это место, где вы получаете правильное имя пользователя и пароль базы данных клиента для этого идентификатора пользователя, и это должно быть вполне возможно.

person Roopesh Shenoy    schedule 03.12.2010
comment
Если весь доступ проходит к БД через хранимые процедуры, может быть возможно сопоставить БД с ORM? - person Marco Staffoli; 03.12.2010
comment
Это возможно, но не рекомендуется - ORM обращается с вашей db как с тупым хранилищем, поэтому, когда у вас есть логика безопасности, встроенная в базу данных, имеет смысл напрямую вызывать SP с использованием классов доступа к данным. - person Roopesh Shenoy; 03.12.2010
comment
DB должен быть тупым магазином. База данных / хранилище данных / постоянное хранилище - это именно то, что предлагает его название - для хранения и сохранения данных. Это не для какой-либо логики. Логика, бизнес или что-то еще должны войти в приложение. SPROC в вашем приложении не безопаснее строковых литералов. И, как я сказал в ответе TFD, если ваше приложение в какой-то момент будет масштабироваться, вы не захотите иметь тысячи пользователей БД и сложные разрешения безопасности. Используйте базу данных как ящик для данных, и ничего больше. Ваша бизнес-логика и мультитенантная логика должны быть в приложении. - person Matt Kocaj; 06.12.2010
comment
Да, логика для отделения сохраненных данных от одного клиента от другого, скорее всего, будет где-то на вашем уровне данных, поскольку это не проблема домена (бизнеса), а скорее инфраструктура. - person Matt Kocaj; 06.12.2010
comment
@cottstak - это скорее выбор дизайна, чем общее правило. Просто потому, что нереляционные БД хороши для масштабирования, мы не отказываемся от использования реляционных БД в целом. Точно так же, если кто-то использует реляционную базу данных, я не вижу причин, почему бы не защитить данные и сам уровень базы данных. Например, Если вы когда-нибудь захотите обеспечить синхронизацию и случайно выберете фреймворк microsoft Sync (что, безусловно, является лучшим выбором в данном случае), дайте мне знать, как вы планируете обеспечить безопасность без разумного использования уровня базы данных. - person Roopesh Shenoy; 06.12.2010
comment
@Roopesh На мой взгляд, все дело в том, чтобы правильно распределять обязанности. Логика домена, такая как бизнес-правила, и логика приложения, такая как управление пользователями и управление арендаторами, относятся к контексту приложения. Сохранение данных, например репликация, синхронизация и выполнение запросов (кэширование и т. Д.), Принадлежит данным в базе данных. Я говорю, что согласен с использованием чего-то вроде репликации MSSQL для репликации или DTC для транзакций, потому что это входит в их зону ответственности. Однако тот факт, что TSQL имеет возможность помещать бизнес-логику в SPROC, не означает, что он принадлежит им. - person Matt Kocaj; 06.12.2010
comment
@cottsak - опять же, я бы сказал, это имеет значение .. от того, какие данные вы храните. А чего добиться проще. Управлять арендаторами в базе данных намного проще. Это также очень важно в корпоративном сценарии, когда несколько приложений могут обращаться к одним и тем же данным. Группе владельцев данных необходимо обеспечить безопасность данных, не полагаясь на команду разработчиков приложений. - person Roopesh Shenoy; 06.12.2010
comment
@ Рупеш Хорошо. Тогда мы просто не согласны. Я категорически против того, чтобы данные рассматривались как отдельная сущность по сравнению с приложением, которое их потребляет. Я не уверен, что такое команда, владеющая данными, но если у меня есть БД, которую использует мое приложение, тогда не нужно делать никаких других подключений к этой БД (за исключением системного администратора, резервного копирования, обслуживания и т. Д.), Кроме тех, которые из моего приложения. Приложение должно быть ответственным за поддержание устойчивости и целостности. Если другому приложению нужны мои данные, оно должно запрашивать их у моего приложения, а не у db. Нет-нет, если мошеннические соединения читают (и не дай бог писать) на мою базу данных. - person Matt Kocaj; 08.12.2010