Как управлять общими и настраиваемыми таблицами - PullRequest
1 голос
/ 11 ноября 2009

У нас много клиентов, использующих наше приложение, и у каждого из них есть своя собственная, идентично структурированная база данных на нашем MS SQL Server. У нас также есть центральная база данных для информации, которая является инвариантной и поэтому используется всеми клиентами, например, база данных почтового индекса USPS. Каждая клиентская база данных имеет представление этих таблиц, например:

create view V_ZIPCode as
select ID, ZIP, City, State
from SharedDB..ZIPCode

Клиенты не имеют прав на изменение данных в SharedDB.

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

Поэтому мне интересно, как лучше реализовать эту ситуацию.

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

Другая идея, которая у меня возникла, состояла в том, чтобы создать идентичные таблицы в SharedDB и клиентской БД, а затем создать представление для клиентской БД следующим образом:

create view V_MyTable as
select ID, Description, convert(bit, 0) IsClientData from SharedDB..MyTable
union
select ID, Description, 1 from MyTable

Чтобы не допустить дублирования идентификатора, я мог бы заполнить значение идентификатора в клиентских таблицах очень большим числом, например, 1 000 000 (больше, чем я когда-либо использовал бы в центральной БД; это довольно стабильные значения поиска); Я не уверен, нужно ли мне вообще это поле IsClientData, но это мелочь. Клиент сможет выбрать все, что он хочет, используя представление, но он сможет изменять данные таблицы только в своей собственной базе данных.

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

Можете ли вы увидеть какие-либо другие проблемы, которые может вызвать этот подход? Можете ли вы порекомендовать какие-либо оптимизации? Или вы бы вообще рекомендовали другой подход?

Если это имеет какое-либо значение, бизнес-уровень приложения пишется на C # с использованием Linq-to-Sql.

1 Ответ

1 голос
/ 11 ноября 2009

Запрет (как вы сказали) на распространение данных по системе, мне кажется довольно солидным.

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

--  In SharedDB
CREATE TABLE CentralTable
 (
   Id              int           not null  identity(1000000, 1)
  ,OwningClientDB  sysname       null
  ,YourDataHere    varchar(100)  not null
  --  Toss in stuff like who added it, when it was added, etc.)
 )

Как вы упомянули, все общие данные добавляются через SET IDENTITY_INSERT CentralTable ON со значениями Id менее 1 000 000 и с Owning ClientDB как нулевым. Затем в каждой клиентской БД:

--  In client DB
CREATE VIEW vCentralTable (Id, OwningClientDB, YourDataHere, etc.) as
 select Id, OwningClientDB, YourDataHere, etc.
  from SharedDB.dbo.CentralTable
  where isnull(OwningClientDB, db_name()) = db_name()

Представление отфильтровывает, какие строки может видеть данный клиент. Я основал фильтр на имени базы данных, но могут быть более эффективные способы сделать это, в зависимости от того, как вы идентифицируете «владеющих» клиентов.

...