实体框架MigrateDatabaseToLatestVersion给出错误

Dav*_*ade 4 entity-framework entity-framework-5

我试图在我的网站上使用基于实体框架代码的迁移.我目前有一个包含多个项目的解决方案.我想要初始化数据库的Web API项目和另一个名为DataLayer项目的项目.我已在DataLayer项目中启用了迁移并创建了一个初始迁移,我希望它将用于创建数据库(如果它不存在).

这是我启用迁移时获得的配置

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" }
        //    );
        //
    }
}
Run Code Online (Sandbox Code Playgroud)

我创建之后对此进行的唯一更改是将其从内部更改为公共,以便WebAPI可以看到它并在其databaseinitializer中使用它.下面是我用来尝试初始化数据库的Application_Start代码中的代码

Database.SetInitializer(new MigrateDatabaseToLatestVersion<ResidentPortalContext, Configuration>());
new ResidentPortalUnitOfWork().Context.Users.ToList();
Run Code Online (Sandbox Code Playgroud)

如果我运行它,无论数据库是否存在,我都会收到以下错误

目录查找文件"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();
Run Code Online (Sandbox Code Playgroud)

数据库将在需要的位置正确创建.

我对造成它的原因感到茫然.可能是我需要在配置类中添加其他东西,还是与我的所有迁移信息都在DataLayer项目中但我从WebAPI项目中调用它这一事实有关?

Dav*_*ade 8

我已经想出了如何为此进程创建动态连接字符串.您需要先将此行添加到Web或App.Config上的EntityFramework条目中,而不是默认情况下放在那里的行.

<defaultConnectionFactory type="<Namespace>.<ConnectionStringFacotry>, <Assembly>"/>  
Run Code Online (Sandbox Code Playgroud)

这告诉程序你有自己的工厂将返回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;
    }
}
Run Code Online (Sandbox Code Playgroud)

一旦我这样做,我就可以在我的Global.asax中运行此代码而没有任何问题

Database.SetInitializer(new MigrateDatabaseToLatestVersion<ResidentPortalContext, Configuration>());
using (ResidentPortalUnitOfWork temp = new ResidentPortalUnitOfWork())
{
    temp.Context.Database.Initialize(true);
}
Run Code Online (Sandbox Code Playgroud)