Создание модели структуры Entity охватывает несколько баз данных
Можно ли сделать что-то вроде
CREATE SYNONYM [dbo].[MyTable] FOR [AnotherDatabase].dbo.[MyTable]
а затем изменить файл Entm Framework edmx, чтобы прочитать этот объект, как и любая другая таблица?
Я сделал быструю пробную проверку и, похоже, отлично работает для выбора и обновления, но я хотел знать, была ли какая-либо причина, почему я не должен делать это
Я получаю определение таблицы, создавая файл edmx, указывающий на вторую базу данных, создавая там сущности, затем копируя/вставляя определение в первый файл edmx базы данных.
ОБНОВЛЕНИЕ
Если кому-то интересно, я написал, что сделал, чтобы создать промежуточные массивы edmx mulitple здесь. Он включает скрипты для генерации синонимов и объединения файлов edmx.
Ответы
Ответ 1
Если вы сделали тест, и это сработало, вы, вероятно, показали что-то, о чем никто больше не знает. До сих пор я всегда отвечал на этот вопрос: невозможно использовать единую модель с двумя базами данных (с более уродливым обходным путем, основанным на представлениях, скрывающих таблицы из второй базы данных). Теперь я знаю два обхода.
Единственным недостатком такого подхода является то, что все изменения, внесенные вручную в часть SSDL вашего EDMX, всегда теряются, если вы запускаете модель обновления из базы данных. Это означает либо ручную разработку EDMX (это довольно тяжелая работа), либо использование некоторого инструмента / script, который добавит ваши изменения после каждого обновления из базы данных.
Ответ 2
Вы также можете сделать это с помощью представлений (и связанного сервера, если другой db находится на другом сервере). Это не позволит вам управлять/объединять два отдельных файла edmx. Я использовал это со связанным сервером для чтения данных со второго db на другом сервере, но провел несколько быстрых тестов, чтобы увидеть, возможно ли обновление/вставки/удаления, и они есть.
У меня нет опыта работы с распределенными транзакциями, поэтому информация, связанная с распределенными транзакциями, может быть хорошей, плохой или немного. Если ваши два db находятся на одном сервере, я ASSUME больше не применяются.
Есть несколько вещей, которые следует иметь в виду при использовании связанного сервера.
- При изменении объектов в связанных таблицах db и вызове
SaveChanges
в вашем контексте это попытается запустить распределенную транзакцию, поэтому, если кто-либо не знает, как остановить это, вам нужно убедиться, что два сервера настроены на обрабатывать распределенные транзакции. (Я бы предположил, что это будет верно и с использованием синонимов).
- Вставки для объектов с столбцами идентификации на связанном сервере вызывают исключение, потому что ef пытается получить новый идентификатор с помощью
SCOPE_IDENTITY()
, и он равен нулю. Я не знаю, есть ли способ обойти это. У меня не было никаких проблем с обновлением или удалением объектов на связанном сервере с столбцами идентификации.
В SQL Server A
- создать связанный сервер с ServerB (пропустите это, если db находятся на одном сервере).
- создать представление в
[ServerA].[MyDB]
для каждой таблицы в [ServerB].[AnotherDB]
, к которой вы хотите получить доступ
В EDMX
- Добавьте свои представления в файл edmx
- Очистить настройку ключа сущности от каждого свойства в конструкторе (включая фактический pk)
- Reset ключ сущности для фактического pk
- Добавить ассоциации по мере необходимости
- Сохранить изменения
Для обновлений/вложений/удалений
- щелкните правой кнопкой мыши на вашем файле edmx и откройте редактор xml.
- Перейдите к
StorageModel
→ Schema
→ EntityContainer
- Найдите объект сущности для объекта и удалите элемент
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
, чтобы добавить этот материал.
Ответ 3
Я обнаружил, что этот трюк с синонимами работает отлично с помощью подхода "Первый код" без каких-либо манипуляций с файлами 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);
}