2013-04-12 3 views
4

Я пытаюсь использовать миграции на основе кода Entity Framework с моего веб-сайта. В настоящее время у меня есть решение с несколькими проектами. Существует проект Web API, который я хочу инициализировать базу данных и другой проект, называемый проектом DataLayer. Я включил миграции в проекте DataLayer и создал начальную миграцию, которая, как я надеюсь, будет использоваться для создания базы данных, если она не существует.Entity Framework MigrateDatabaseToLatestVersion дает ошибку

Вот конфигурация, которую я получил, когда я включил миграции

public sealed class Configuration : DbMigrationsConfiguration<Harris.ResidentPortal.DataLayer.ResidentPortalContext> 
{ 
    public Configuration() 
    { 
     AutomaticMigrationsEnabled = false; 
    } 

    protected override void Seed(Harris.ResidentPortal.DataLayer.ResidentPortalContext context) 
    { 
     // This method will be called after migrating to the latest version. 

     // You can use the DbSet<T>.AddOrUpdate() helper extension method 
     // to avoid creating duplicate seed data. E.g. 
     // 
     // context.People.AddOrUpdate(
     //  p => p.FullName, 
     //  new Person { FullName = "Andrew Peters" }, 
     //  new Person { FullName = "Brice Lambson" }, 
     //  new Person { FullName = "Rowan Miller" } 
     // ); 
     // 
    } 
} 

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

Database.SetInitializer(new MigrateDatabaseToLatestVersion<ResidentPortalContext, Configuration>()); 
new ResidentPortalUnitOfWork().Context.Users.ToList(); 

Если я запускаю существует это или нет базы данных я получаю следующую ошибку

поиск Каталог для файла «C: \ Users \ Dave \ Documents \ Visual Studio 2012 \ Projects \ ResidentPortal \ Harris.ResidentPortal.WebApi \ App_Data \ Harris.ResidentPortal.DataLayer.ResidentPortalContext.mdf" не удалось с ошибкой операционной системы 2 (система не может найдите указанный файл.).

CREATE DATABASE не удалось. Некоторые имена файлов не могут быть созданы. Проверьте связанные ошибки.

Похоже, что он находится в совершенно неправильном месте базы данных. Кажется, что это связано с этим конкретным способом. Я инициализирую базу данных, потому что если я изменил код на следующий.

Database.SetInitializer(new DropCreateDatabaseAlways<ResidentPortalContext>()); 
new ResidentPortalUnitOfWork().Context.Users.ToList(); 

База данных будет правильно создана там, где ей нужно идти.

Я в затруднении за то, что вызывает его. Может быть, мне нужно добавить что-то еще в класс конфигурации или это связано с тем фактом, что вся моя информация о миграции находится в проекте DataLayer, но я вызываю это из проекта WebAPI?

+0

кажется, что-то со строкой соединения, и путь вы направляете вы настроили для SQL сервер. Я бы удостоверился, что строка подключения настроена правильно, и вы можете достичь и написать все, что вам нужно. –

+0

Мне тоже было интересно, но если я могу просто отключить одну строку MigrateDatabaseToLatestVersion и заменить ее DropCreateDatabaseAlways, и она отлично работает, тогда я думаю, что строка соединения не будет проблемой, потому что оба будут использовать ее –

+0

OK У меня есть вычислил это, и это действительно связано с строкой соединения, но я догадываюсь, что я все еще запутался относительно того, как другая стратегия работала. Мы используем шаблон проектирования UnitOfWork, и когда вы строите UnitOfWork, он создает контекст и передает ему строку соединения, поэтому нам не нужно было в файле Web Config. Я должен был поместить строку соединения в Web.Config, чтобы заставить это работать при использовании стратегии MigrateDatabaseToLatestVersion, но theDropCrerateDatabaseAlways работал без проблем. Я использовал UnitOfWork для создания контекста перед инициализацией базы данных. Зачем?? –

ответ

8

Я выяснил, как создать динамическую строку соединения для этого процесса. Вы должны сначала добавить эту строку в свою запись EntityFramework в Web или App.Config вместо строки, которая по умолчанию будет помещена туда.

<defaultConnectionFactory type="<Namespace>.<ConnectionStringFacotry>, <Assembly>"/> 

Это говорит программе, что у вас есть собственный завод, который вернет DbConnection. Ниже приведен код, который я использовал для создания собственной фабрики. Часть этого - это взломать тот факт, что кучка программистов работает с одним и тем же набором кода, но некоторые из нас используют SQL Express, а другие используют полностью раздутый SQL Server. Но это даст вам пример для того, чтобы идти тем, что вам нужно.

public sealed class ResidentPortalConnectionStringFactory: IDbConnectionFactory 
{ 
    public DbConnection CreateConnection(string nameOrConnectionString) 
    { 
     SqlConnectionStringBuilder builder = new SqlConnectionStringBuilder(ConfigurationManager.ConnectionStrings["PortalDatabase"].ConnectionString); 

     //save off the original catalog 
     string originalCatalog = builder.InitialCatalog; 

     //we're going to connect to the master db in case the database doesn't exist yet 
     builder.InitialCatalog = "master"; 
     string masterConnectionString = builder.ToString(); 

     //attempt to connect to the master db on the source specified in the config file 
     using (SqlConnection conn = new SqlConnection(masterConnectionString)) 
     { 
      try 
      { 
       conn.Open(); 
      } 
      catch 
      { 
       //if we can't connect, then append on \SQLEXPRESS to the data source 
       builder.DataSource = builder.DataSource + "\\SQLEXPRESS"; 
      } 
      finally 
      { 
       conn.Close(); 
      } 
     } 

     //set the connection string back to the original database instead of the master db 
     builder.InitialCatalog = originalCatalog; 

     DbConnection temp = SqlClientFactory.Instance.CreateConnection(); 
     temp.ConnectionString = builder.ToString(); 

     return temp; 
    } 
} 

После того, как я сделал, что я coudl запустить этот код в моем Global.asax без проблем

Database.SetInitializer(new MigrateDatabaseToLatestVersion<ResidentPortalContext, Configuration>()); 
using (ResidentPortalUnitOfWork temp = new ResidentPortalUnitOfWork()) 
{ 
    temp.Context.Database.Initialize(true); 
} 
Смежные вопросы