59

У меня есть один проект, который я хочу запустить в моем update-database, но у меня есть мои модели и контекст в отдельном проекте.Включить миграцию с помощью контекста в отдельной сборке?

Если я запустил enable-migrations, я получаю эту ошибку: В сборке 'MyProject' не был указан контекстный тип.

Это, по-видимому, потому, что мой контекст находится в MyProject.MVC.

Если я запустил enable-migrations против MyProject.MVC, я должен добавить файл конфигурации приложения. Я не хочу этого делать, поскольку я хочу использовать код для многих проектов.

Могу ли я запустить enable-migrations против MyProject и как-то сказать ему посмотреть в MyProject.MVC для контекста?

+0

PM> enable-migrations -projectname yourproject –

ответ

90

Это будет работать только в EF 6, но есть release, который добавил параметр -ContextProjectName в команду -enable-migrations. С помощью этой команды вы можете сделать следующее:

enable-migrations -ContextProjectName MyProject.MVC -StartUpProjectName MyProject.MVC 
-ContextTypeName MyProject.MVC.MyContextFolder.MyContextName -ProjectName MyProject 

Это добавит миграции в свой MyProject проект, используя контекст в MyProject.MVC. Вы должны убедиться, что проект с Миграции имеет ссылку на проект с вашего контекста, то есть, MyProject ссылки MyProject.MVC

+6

Это правильный способ сделать это, я удивлен @Jon не принял это как ответ. – JARRRRG

+0

Это сделало мою работу. Спасибо @SOfanatic – Alaor

+0

Если 'MyProject' имеет контекст для' MyProject.MVC', не будет ли это создавать циклическую зависимость? – Arithmomaniac

0

У меня была такая же проблема, и я использую EntityFramework 4.3.1. Кажется, что EF6 решает эту проблему (в соответствии с ответом @SOfanatic), но я не хотел обновляться до EF6 из-за некоторых нарушений (например, в DataAnnotations).

Итак, что я сделал, чтобы решить эту проблему (и то, что я узнал в процессе):

  1. Создать новое решение (пустой проект) и добавить проект, в котором у вас есть модель, которую вы хотите включить миграции для (в вашем случае MyProject.MVC). Возможно, вам потребуется установить для него необходимые пакеты NuGet, прежде чем вы сможете добавить существующий проект.

  2. Добавить конфигурационный файл со строкой подключения (не беспокойтесь, это только для того, чтобы обмануть механизм миграции). Скопируйте существующую базу данных в выходную папку проекта модели (должен быть MVC \ bin \ Debug в вашем случае). Убедитесь, что строка подключения в файле конфигурации указывает на этой базе данных:

    <connectionStrings> 
        <add name="MyDB" providerName="System.Data.SqlServerCe.4.0" connectionString="DataSource=|DataDirectory|\MyDB.sdf"/> 
        </connectionStrings> 
    
  3. Поскольку вы в новое решение, установить типовой проект как проект запуска (вы можете удалить проект по умолчанию).

  4. Запустите команду enable-migrations в консоли диспетчера пакетов. Он должен создать папку Migrations с двумя файлами: Configuration.cs и timestamped файл InitialCreate.cs. Приятно иметь InitialCreate, поэтому вы помещаете свою существующую базу данных в выходную папку проекта модели (но это необязательно).

  5. Обновите исходное решение, чтобы эти изменения были обновлены.

То, что я узнал (насколько я понимаю):

  1. миграции двигатель нужно что-то, что выглядит как допустимое подключение к работе. Я создал строку подключения в коде (в другом проекте), и это не сработало. Я просто дал движку Migrations «правильную» строку подключения, чтобы заставить ее работать.
  2. Поместите свою базу данных туда, где механизм миграции может найти ее (например, выходную папку модели проекта), поэтому она создает отправную точку для миграции. Эта отправная точка - это в основном ваша схема базы данных, написанная в API миграции.
  3. Вы можете восстановить все до своего предыдущего состояния после того, как миграция будет установлена ​​на место, и она будет работать нормально.
  4. Каждый раз, когда вы хотите вручную добавить перенос, вы должны снова «обмануть» механизм миграции, как и в первый раз. Я не пробовал с автоматическими переходами, я думаю, этот подход работает.

К слову, я использую базу данных SQL Server CE 4.0, поэтому некоторые вещи о строке подключения немного отличаются от стандартной базы данных SQL Server или LocalDB. Кроме того, все то же самое.

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

11

В проект, содержащий класс контекста базы данных, можно запускать только «Включить-Миграции».

Ваше решение будет содержать 2 проекта:

1) MyProject.Models 
    |- Migrations 
     |- 201401061557314_InitialCreate.cs 
     |- Configuration.cs 
    |- MyContext.cs 
    |- App.config (no connection string) 


App.config

<?xml version="1.0" encoding="utf-8"?> 
<configuration> 
    <configSections> 
    <section name="entityFramework" type="System.Data.Entity.Internal.ConfigFile.EntityFrameworkSection, EntityFramework, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" requirePermission="false" /> 
    </configSections> 
    <entityFramework> 
    <defaultConnectionFactory type="System.Data.Entity.Infrastructure.SqlConnectionFactory, EntityFramework" /> 
    <providers> 
     <provider invariantName="System.Data.SqlClient" type="System.Data.Entity.SqlServer.SqlProviderServices, EntityFramework.SqlServer" /> 
    </providers> 
    </entityFramework> 
</configuration> 


2) MyProject.MVC 
     |- Filters 
      |- InitializeSimpleMembershipAttribute.cs 


InitializeSimpleMembershipAttribute.cs

namespace MyProject.MVC.Filters 
{ 
    [AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, AllowMultiple = false, Inherited = true)] 
    public sealed class InitializeSimpleMembershipAttribute : ActionFilterAttribute 
    { 
     private static SimpleMembershipInitializer _initializer; 
     private static object _initializerLock = new object(); 
     private static bool _isInitialized; 

     public override void OnActionExecuting(ActionExecutingContext filterContext) 
     { 
      // Ensure ASP.NET Simple Membership is initialized only once per app start 
      LazyInitializer.EnsureInitialized(ref _initializer, ref _isInitialized, ref _initializerLock); 
     } 

     private class SimpleMembershipInitializer 
     { 
      public SimpleMembershipInitializer() 
      { 
       try 
       { 
        Database.SetInitializer<MyContext>(new MigrateDatabaseToLatestVersion<MyContext, MyProject.Model.Migrations.Configuration>()); 

        using (var context = new MyContext()) 
        { 
         context.Database.Initialize(force: true); 
         if (!context.Database.Exists()) 
         { 
          // Create the SimpleMembership database without Entity Framework migration schema 
          ((IObjectContextAdapter)context).ObjectContext.CreateDatabase(); 
         } 
        } 

        WebSecurity.InitializeDatabaseConnection("DefaultConnection", "UserProfile", "UserId", "UserName", autoCreateTables: true); 
       } 
       catch (Exception ex) 
       { 
        throw new InvalidOperationException("The ASP.NET Simple Membership database could not be initialized. For more information, please see http://go.microsoft.com/fwlink/?LinkId=256588", ex); 
       } 
      } 
     } 
    } 
} 

Набор MyProject.MVC как проект запуска

В менеджере пакетов выберите проект: MyProject.Models

Затем запустите "Enable-Миграции", чтобы создать Папка «Миграции» в MyProject.Models

В соответствии с «Обновить базу данных» -> миграция s будет использовать строку подключения в Web.config из проекта запуска для выполнения миграции

2

Вот обходной путь:

Добавить класс в MyProject (проект по миграции). Сделать этот класс наследовать dbcontext (тот, что в MyProject.MVC).

Затем выполните команды миграции EF в MyProject.

Смежные вопросы