Создание модели 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 предположим распределенные транзакции больше не применяются.

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

  1. при изменении сущностей в связанных таблицах БД и вызове SaveChanges в вашем контексте это попытается запустить распределенную транзакцию, поэтому, если кто-то не знает, как это остановить, вам нужно убедиться, что два сервера настроены для обработки распределенных транзакций. (Я бы предположил, что это будет верно, используя синонимы тоже).
  2. вставки на сущностях со столбцами идентификаторов на связанном сервере вызывают исключение, потому что ef пытается получить новый идентификатор с помощью SCOPE_IDENTITY() и это null. Я не знаю, есть ли способ обойти это. У меня не было проблем с обновлением или удалением сущностей на связанном сервере со столбцами идентификаторов.

на SQL Server А

  1. создайте связанный сервер с ServerB (пропустите это, если БД находятся на одном сервере).
  2. создать представление в [ServerA].[MyDB] для каждой таблицы в [ServerB].[AnotherDB] вы хотите получить доступ к

в edmx-файла

  1. добавьте свои представления в файл edmx
  2. очистите параметр ключа сущности от каждого свойства в конструкторе (включая фактический pk)
  3. сброс ключа сущности для фактического pk
  4. добавить ассоциации по мере необходимости
  5. Сохранить изменения

Для Обновления/Вставки/Удаления

  1. щелкните правой кнопкой мыши на файле edmx и откройте с помощью XML editor
  2. перейти к StorageModel ->Schema ->EntityContainer
  3. найдите entityset для вашей сущности и удалите DefiningQuery элемент
  4. найти store:Schema атрибут в наборе сущностей и удалить store: так что это просто Schema. Оставьте его ценность в покое.
  5. повторите шаги 3 и 4 для каждого представления со связанного сервера
  6. Сохранить изменения

поскольку использование связанного сервера создает распределенную транзакцию, мне пришлось сделать пару вещей на 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);
    }