2012-03-07 3 views
3

Моя БД разработки - 2008 R2, где Code First генерирует локальную базу данных с DropCreateIfModelChanges.Код для SQL Server 2005?

Мой метод развертывания для производства - генерировать скрипты из локальной БД, включая данные и запускать их в процессе производства. Это создает все таблицы, включая таблицу EdmMetadata, и заполняет ее хешем.

Работы: Запустить сценарий в другом экземпляре 2008 R2, изменить строку соединения для модели Entity, чтобы указать на этот производственный экземпляр, запустить приложение.

Не работает: Запустите скрипт в другом экземпляре 2005 года, измените строку подключения для модели Entity, чтобы указать на этот производственный экземпляр, запустите приложение. Я получаю сообщение об ошибке изменения модели.

Я думаю, что это не работает, потому что версия совместимости с БД является частью хэша. таким образом, в процессе производства он генерирует хэш и сравнивает его с хешем, хранящимся в таблице EdmMetadata. Новый хеш отличается тем, что он генерируется по сравнению с БД 2005 года.

Я предполагаю, что у меня не было бы этой проблемы, если бы я создавал локальную базу данных 2005 года и развертывал ее в экземпляре 2005 года. Однако у меня нет установленного 2005 года и, скорее всего, не потребуется всем разработчикам устанавливать его, когда 2008 год поддерживает режим совместимости 2005 года.

Как заставить EF генерировать БД в режиме совместимости 2005 года?

+0

Вы пытались создать сценарий из консоли PM напрямую? то есть «Update-Database -Script» - это часть функций миграции (говоря о 4.3). Затем сделайте это вручную. Вся часть миграции создана для таких вещей, я не уверен и не имею возможности проверить это прямо сейчас, но я думаю, что вам следует просто следовать рекомендованному маршруту здесь, использовать миграцию (и/или сценарии до создания Db) и у вас не должно быть проблем. Если вы используете «SqlConnectionFactory», который по умолчанию должен быть в порядке, работайте. – NSGaga

ответ

2

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

Database.SetInitializer<MyContext>(null); 

Но это, наверное, лучше сделать это в app.config/web.config для производства приложения, как так:

<entityFramework> 
    <contexts> 
    <context type="MyNamespace.MyContext, MyAssembly" disableDatabaseInitialization="true" /> 
    </contexts> 
</entityFramework> 

Вы должны обновите до EF 4.3 для этого синтаксиса - см. http://blogs.msdn.com/b/adonet/archive/2012/01/12/ef-4-3-configuration-file-settings.aspx. Существует также способ сделать это в EF 4.1: см. http://blog.oneunicorn.com/2011/03/31/configuring-database-initializers-in-a-config-file/.

Вы также можете попробовать просто обновить до EF 4.3, который больше не использует таблицу EdmMetadata - вместо этого он использует таблицу __MigrationHistory. Это проверяет совместимость модели по-другому. Он может по-прежнему указывать разницу, если бы Code First создавал другую базу данных за 2005 год, чем в 2008 году, что случается иногда.

Вы можете установить SQL Server 2005 Express в своем блоке dev. Это бесплатно и будет лучше соответствовать вашей производственной среде.

И наконец, если ни одно из вышеперечисленных действий не работает, и вам необходимо принудительно создать код First для создания модели 2005 года/базы данных, тогда вы можете это сделать, но это означает использование нижних уровней строительных блоков. Во-первых, вам нужно создать DbModelBuilder себя и называть Entity для каждого из типов объектов, для которых у вас есть DbSet заявил на своем контексте:

var modelBuilder = new DbModelBuilder(); 
modelBuilder.Entity<User>(); 
modelBuilder.Entity<Blog>(); 

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

Как только вы настроили DbModelBuilder, вам нужно будет собрать и скомпилировать, чтобы получить скомпилированную модель, которая может быть передана в DbContext. На этом этапе вы можете пройти в «2005» в качестве токена манифеста поставщика.

var compiledModel = modelBuilder 
    .Build(new DbProviderInfo("System.Data.SqlClient", "2005")) 
    .Compile(); 

Теперь вы должны кэшировать эту скомпилированную модель в домене приложения, чтобы вы только ее составляли и компилировали один раз. (Обычно DbContext делает это для вас, когда он создает модель, но если вы сами создаете модель, вам также нужно сделать кэширование самостоятельно.)

Наконец, вам нужно передать скомпилированную модель в конструктор вашего контекст каждый раз, когда вам нужно его использовать, и чтобы этот конструктор передал модель базовому конструктору.

public class MyContext : DbContext 
{ 
    public MyContext(DbCompiledModel model) 
     : base(model) 
    { 
    } 

    public DbSet<User> Users { get; set; } 
    public DbSet<Blog> Blogs { get; set; } 
} 

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

+0

+1 Спасибо, я попробую это в следующий раз, когда я развернусь. Мне нравится идея сделать это в конфиге, так как я могу поместить его в web.Production.config преобразовать специально для конфигурации сборки сборки/развертывания. – AaronLS