Создание модели Entity Framework для нескольких баз данных
допустимо ли делать что-то вроде
CREATE SYNONYM [dbo].[MyTable] FOR [AnotherDatabase].dbo.[MyTable]
а затем изменить edmx-файл Entity Framework, чтобы прочитать этот объект, как и любую другую таблицу?
Я сделал быстрый тест образца, и он, похоже, отлично работает для выбора и обновления, но я хотел знать, есть ли причина, по которой я не должен этого делать
Я получаю определение таблицы, создавая файл edmx, указывающий на 2-ю базу данных, создавая сущности там, затем скопируйте / вставьте определение в файл edmx 1-й базы данных.
обновление
Если кто-то заинтересован, я написал, что я сделал, чтобы сделать edmx-файл span mulitple databases здесь. Он включает в себя скрипты для генерации синонимов и слияния файлов edmx.
3 ответов
Если вы сделали тест, и он сработал, вы, вероятно, показали что-то еще никто не знает. До сих пор я всегда отвечал на этот вопрос: невозможно использовать одну модель с двумя базами данных (с более уродливым обходным путем, основанным на представлениях, скрывающих таблицы из второй базы данных). Теперь я знаю два обходных пути.
единственным недостатком этого подхода является то, что все изменения, внесенные вручную в SSDL-часть вашего EDMX, всегда теряются при запуске обновить модель из база данных. Это означает либо ручную разработку EDMX (что довольно сложно), либо использование некоторого инструмента / скрипта, который добавит ваши изменения после каждого обновления из базы данных.
вы также можете сделать это с представлениями (и связанным сервером, если другая БД находится на другом сервере). Это избавит вас от необходимости управлять/объединять два отдельных файла edmx. Я использовал это со связанным сервером для чтения данных из второй БД на другом сервере, но провел несколько быстрых тестов, чтобы узнать, возможны ли обновления/вставки/удаления, и они есть.
у меня нулевой опыт работы с распределенными транзакциями, поэтому информация, связанная с распределенными транзакциями может быть хорошим, плохим или и тем и другим. если ваши две БД находятся на одном сервере I предположим распределенные транзакции больше не применяются.
есть несколько вещей, чтобы иметь в виду при использовании связанного сервера.
- при изменении сущностей в связанных таблицах БД и вызове
SaveChanges
в вашем контексте это попытается запустить распределенную транзакцию, поэтому, если кто-то не знает, как это остановить, вам нужно убедиться, что два сервера настроены для обработки распределенных транзакций. (Я бы предположил, что это будет верно, используя синонимы тоже). - вставки на сущностях со столбцами идентификаторов на связанном сервере вызывают исключение, потому что ef пытается получить новый идентификатор с помощью
SCOPE_IDENTITY()
и это null. Я не знаю, есть ли способ обойти это. У меня не было проблем с обновлением или удалением сущностей на связанном сервере со столбцами идентификаторов.
на SQL Server А
- создайте связанный сервер с ServerB (пропустите это, если БД находятся на одном сервере).
- создать представление в
[ServerA].[MyDB]
для каждой таблицы в[ServerB].[AnotherDB]
вы хотите получить доступ к
в edmx-файла
- добавьте свои представления в файл edmx
- очистите параметр ключа сущности от каждого свойства в конструкторе (включая фактический pk)
- сброс ключа сущности для фактического pk
- добавить ассоциации по мере необходимости
- Сохранить изменения
Для Обновления/Вставки/Удаления
- щелкните правой кнопкой мыши на файле edmx и откройте с помощью XML editor
- перейти к
StorageModel
->Schema
->EntityContainer
- найдите entityset для вашей сущности и удалите
DefiningQuery
элемент - найти
store:Schema
атрибут в наборе сущностей и удалитьstore:
так что это простоSchema
. Оставьте его ценность в покое. - повторите шаги 3 и 4 для каждого представления со связанного сервера
- Сохранить изменения
поскольку использование связанного сервера создает распределенную транзакцию, мне пришлось сделать пару вещей на ObjectContext
до SaveChanges
прошла успешно.
ctx.Connection.Open();
ctx.ExecuteStoreCommand("set xact_abort on");
ctx.SaveChanges();
ctx.Connection.Close();
вы, вероятно, можете создать пользовательскую ObjectContext
и переопределить SaveChanges
чтобы добавить этот материал.
Я обнаружил, что этот трюк с синонимами работает отлично С подходом "код первый" без каких-либо манипуляций с файлами edmx!
единственное, что вам нужно сделать, это "привязать" свой класс к соответствующему синониму в методе OnModelCreating вашего DataContext.
например, Если у меня есть синоним таблицы персонала в другой БД (и имя класса также персонал), и имя синонима "схеме myschema.MySynonym" тогда метод OnModelCreating должен выглядеть так:
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.HasDefaultSchema("myschema");
modelBuilder.Entity<Personnel>()
.ToTable("MySynonym");
Database.SetInitializer<TestSynonymContext>(null);
base.OnModelCreating(modelBuilder);
}