Автоматизация DDL в .Net - PullRequest
       5

Автоматизация DDL в .Net

1 голос
/ 25 августа 2010

У меня есть продукт, который имеет собственный уровень доступа к данным, запрограммированный на C ++ / COM для использования с конструктором веб-приложений на базе Windows, и ему уже не менее 10 лет. Этот DAL модульный с чем-то похожим на провайдеров данных, так что он может генерировать базовый SQL и DDL для определенного типа базы данных.

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

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

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

Мои вопросы довольно велики по объему, поэтому я не ищу конкретные ответы, только указатели. Каковы варианты продолжения работы с этим подходом? Есть ли лучшие варианты разрешения динамической схемы, о которых я не знаю? Каковы основные преимущества и недостатки других возможных подходов?

Ответы [ 2 ]

1 голос
/ 08 марта 2011

Вы пометили этот вопрос как «.net», плюс вы говорите, что экспериментировали с nHibernate, поэтому я делаю скачок, чтобы предположить, что вы пытаетесь перейти на .NET и от COM. Я также предполагаю, что вы используете Microsoft SQL Server, хотя нет особой причины, по которой это должно иметь место (например, принудительное использование внешних ключей исторически было «функцией» MySQL).

Entity Framework, вероятно, может помочь вам в том, что касается уровня доступа к данным, но вы столкнетесь с такими же ограничениями. Что вы, возможно, могли бы сделать, так это продолжить основанный на XML подход, о котором вы упоминали, и расширить модели данных с помощью частичных классов, которые работают вместе с классами Entity Framework. Затем вы могли бы написать методы, которые извлекали бы определенные псевдополя из столбца XML и возвращали их, помогая более или менее отделить ваш уровень доступа к данным от остальной части вашего приложения.

Тем не менее, я бы внимательно посмотрел на ваше моделирование данных и выяснил, действительно ли этот динамический подход действительно необходим. Какие виды данных вы храните? Не могли бы вы обработать, скажем, Сложные типы сущностей в Entity Framework 4? Я почти уверен, что свежий взгляд на моделирование данных и бизнес-требования вашего приложения даст способ сделать что-то более нормализованное, чем динамическая схема.

0 голосов
/ 08 марта 2011

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

    Create trigger [DDLTRack]
ON Database for

CREATE_ASSEMBLY         ,ALTER_ASSEMBLY         ,DROP_ASSEMBLY
,CREATE_ASYMMETRIC_KEY  ,ALTER_ASYMMETRIC_KEY   ,DROP_ASYMMETRIC_KEY
                        --,ALTER_AUTHORIZATION
                        ,ALTER_AUTHORIZATION_DATABASE 
,CREATE_CERTIFICATE     ,ALTER_CERTIFICATE      ,DROP_CERTIFICATE
,CREATE_CONTRACT                                ,DROP_CONTRACT          
--,ADD_COUNTER_SIGNATURE                            
--,DROP_COUNTER_SIGNATURE
--,CREATE_CREDENTIAL        ,ALTER_CREDENTIAL       ,DROP_CREDENTIAL
                                                                ,GRANT_DATABASE ,DENY_DATABASE  ,REVOKE_DATABASE
,CREATE_DEFAULT                                 ,DROP_DEFAULT
                                                                ,BIND_DEFAULT   --,UNBIND_DEFAULT   
,CREATE_EVENT_NOTIFICATION                      ,DROP_EVENT_NOTIFICATION
,CREATE_EXTENDED_PROPERTY   --,ALTER_EXTENDED_PROPERTY  
,DROP_EXTENDED_PROPERTY  
,CREATE_FULLTEXT_CATALOG    ,ALTER_FULLTEXT_CATALOG ,DROP_FULLTEXT_CATALOG  
--,CREATE_FULLTEXT_INDEX        ,ALTER_FULLTEXT_INDEX   ,DROP_FULLTEXT_INDEX 
,CREATE_FUNCTION            ,ALTER_FUNCTION         ,DROP_FUNCTION
--,CREATE_INDEX             ,ALTER_INDEX            ,DROP_INDEX
--,CREATE_MASTER_KEY            ,ALTER_MASTER_KEY       ,DROP_MASTER_KEY
,CREATE_MESSAGE_TYPE        ,ALTER_MESSAGE_TYPE     ,DROP_MESSAGE_TYPE
,CREATE_PARTITION_FUNCTION  ,ALTER_PARTITION_FUNCTION   ,DROP_PARTITION_FUNCTION
,CREATE_PARTITION_SCHEME    ,ALTER_PARTITION_SCHEME     ,DROP_PARTITION_SCHEME
,CREATE_PLAN_GUIDE          ,ALTER_PLAN_GUIDE           ,DROP_PLAN_GUIDE 
,CREATE_PROCEDURE           ,ALTER_PROCEDURE            ,DROP_PROCEDURE
,CREATE_QUEUE               ,ALTER_QUEUE                ,DROP_QUEUE
,CREATE_REMOTE_SERVICE_BINDING  ,ALTER_REMOTE_SERVICE_BINDING   ,DROP_REMOTE_SERVICE_BINDING
--,CREATE_SPATIAL_INDEX                                                                 
--  ,RENAME   
,CREATE_ROLE                ,ALTER_ROLE                 ,DROP_ROLE  
--,ADD_ROLE_MEMBER                                      ,DROP_ROLE_MEMBER
,CREATE_ROUTE               ,ALTER_ROUTE                ,DROP_ROUTE
,CREATE_RULE                                            ,DROP_RULE              
                                                                                            ,BIND_RULE  ,UNBIND_RULE 
,CREATE_SCHEMA              ,ALTER_SCHEMA               ,DROP_SCHEMA
,CREATE_SERVICE             ,ALTER_SERVICE              ,DROP_SERVICE
--,ALTER_SERVICE_MASTER_KEY                 
--,BACKUP_SERVICE_MASTER_KEY    
--,RESTORE_SERVICE_MASTER_KEY
--,ADD_SIGNATURE                                            ,DROP_SIGNATURE

--,CREATE_STATISTICS                                        ,DROP_STATISTICS                    ,UPDATE_STATISTICS
--,CREATE_SYMMETRIC_KEY     ,ALTER_SYMMETRIC_KEY        ,DROP_SYMMETRIC_KEY
,CREATE_SYNONYM                                         ,DROP_SYNONYM
,CREATE_TABLE               ,ALTER_TABLE                ,DROP_TABLE
,CREATE_TRIGGER             ,ALTER_TRIGGER              ,DROP_TRIGGER
,CREATE_TYPE                                            ,DROP_TYPE
,CREATE_USER                ,ALTER_USER                 ,DROP_USER 
,CREATE_VIEW                ,ALTER_VIEW                 ,DROP_VIEW
,CREATE_XML_INDEX           
,CREATE_XML_SCHEMA_COLLECTION   ,ALTER_XML_SCHEMA_COLLECTION    ,DROP_XML_SCHEMA_COLLECTION


as 
insert ddlTracking..ddlLog(TSQL,SchemaName,ObjectName,ObjectType,eventXML,LoginName,dbName,EventType)
Select EVENTDATA().value('(/EVENT_INSTANCE/TSQLCommand/CommandText)[1]','nvarchar(max)')
       ,EVENTDATA().value('(/EVENT_INSTANCE/SchemaName)[1]','nvarchar(max)')
       ,EVENTDATA().value('(/EVENT_INSTANCE/ObjectName)[1]','nvarchar(max)')
       ,EVENTDATA().value('(/EVENT_INSTANCE/ObjectType)[1]','nvarchar(max)')
       ,EVENTDATA()
       ,EVENTDATA().value('(/EVENT_INSTANCE/LoginName)[1]','nvarchar(max)')
       ,EVENTDATA().value('(/EVENT_INSTANCE/DatabaseName)[1]','nvarchar(max)')
       ,EVENTDATA().value('(/EVENT_INSTANCE/EventType)[1]','nvarchar(max)')






GO

SET ANSI_NULLS OFF
GO

SET QUOTED_IDENTIFIER OFF
GO

DISABLE TRIGGER [DDLTRack] ON DATABASE
GO

ENABLE TRIGGER [DDLTRack] ON DATABASE
GO

. Это внесет все ваши изменения

в (в данном случае)Таблица DDlTrack.dbo.DDLlog. Затем вы можете сгруппировать последние изменения, сделанные в объекте базы данных, отфильтровав необходимые записи в базе данных-источнике и применив их к цели.НТН.

...