10

我尝试在以下位置设置MyProject\App_Data\Cos.mdf数据库的位置App.config

 <connectionStrings>
    <add name="DefaultConnection" connectionString="Data Source=(LocalDb)\v11.0;AttachDbFilename=|DataDirectory|\Cos.mdf;Initial Catalog=Cos;Integrated Security=True;MultipleActiveResultSets=True" providerName="System.Data.SqlClient" />
  </connectionStrings>

Program.cs我写道:

 static void Main(string[] args) {

        string relative = @"..\..\App_Data\Cos.mdf";
        string absolute = Path.GetFullPath(relative);

        AppDomain.CurrentDomain.SetData("DataDirectory", absolute); 
        Console.WriteLine(absolute);
        Console.ReadKey();
 }

显示的路径是(我贴出来说明我没有记错):

在此处输入图像描述

但是当我输入包管理器控制台enable-migrations更改AutomaticMigrations为true时,然后输入update-database我得到错误:

Cannot attach the file 'C:\Users\s8359_000\Documents\Visual Studio 2013\Projects\Projekt5 — kopia\Projekt5\bin\Debug\Cos.mdf' as database 'Cos'.

为什么 .NET 会尝试在Debug目录中创建我的数据库?!我在 StackOverflow 上浏览了关于这个主题的 15 个主题,看起来每个人都只是重复了不起作用的答案。

回答 SRUTZKY 后编辑 是的,你是对的,有错误。在您回答后,我尝试了更多组合,不幸的是没有一个有效。

  <connectionStrings>
    <add name="DefaultConnection" connectionString="Data Source=(LocalDb)\v11.0;AttachDbFilename=|DataDirectory|\baza.mdf;Initial Catalog=baza;Integrated Security=True;MultipleActiveResultSets=True" providerName="System.Data.SqlClient" />
  </connectionStrings>

和主要

  static void Main(string[] args) {

        Console.WriteLine("BEFORE:" + AppDomain.CurrentDomain.GetData("DataDirectory"));
        string relative = @"..\..\App_Data\Cos.mdf";
        string absolute = Path.GetFullPath(relative);
        absolute = Path.GetDirectoryName(@absolute);
        AppDomain.CurrentDomain.SetData("DataDirectory", @absolute);
        Console.WriteLine(@absolute);
        Console.WriteLine(AppDomain.CurrentDomain.GetData("DataDirectory"));
        Console.ReadKey();
}

然后我进入控制台:

在此处输入图像描述

在删除Migrations目录和之后enable-migrations,自动迁移到 true,update-database我得到:

PM> update-database 指定“-Verbose”标志以查看应用于目标数据库的 SQL 语句。System.Data.SqlClient.SqlException (0x80131904):发生文件激活错误。物理文件名“\baza.mdf”可能不正确。诊断并更正其他错误,然后重试该操作。创建数据库失败。无法创建列出的某些文件名。检查相关错误。在 System.Data.SqlClient.SqlConnection.OnError(SqlException 异常,布尔 breakConnection,操作1 wrapCloseInAction) at System.Data.SqlClient.SqlInternalConnection.OnError(SqlException exception, Boolean breakConnection, Action1 wrapCloseInAction) 在 System.Data.SqlClient.TdsParser.ThrowExceptionAndWarning(TdsParserStateObject stateObj, Boolean callerHasConnectionLock, Boolean asyncClose) 在 System.Data.SqlClient.TdsParser.TryRun(RunBehavior runBehavior, SqlCommand cmdHandler, SqlDataReader dataStream, BulkCopySimpleResultSet bulkCopyHandler, TdsParserStateObject state&Obj, Boolean dataReady) 在 System.Data.SqlClient.SqlCommand.RunExecuteNonQueryTds(String methodName, Boolean async, Int32 timeout, Boolean asyncWrite) 在 System.Data.SqlClient.SqlCommand.InternalExecuteNonQuery(TaskCompletionSource 1 completion, String methodName, Boolean sendToPipe, Int32 timeout, Boolean asyncWrite) at System.Data.SqlClient.SqlCommand.ExecuteNonQuery() at System.Data.Entity.Infrastructure.Interception.DbCommandDispatcher.<NonQuery>b__0(DbCommand t, DbCommandInterceptionContext1 c) 在 System.Data.Entity.Infrastructure.Interception .InternalDispatcher 1.Dispatch[TTarget,TInterceptionContext,TResult](TTarget target, Func3 操作,TInterceptionContext,interceptionContext,Action3 executing, Action3 执行)在 System.Data.Entity.SqlServer.SqlProviderServices 的 System.Data.Entity.Infrastructure.Interception.DbCommandDispatcher.NonQuery(DbCommand command, DbCommandInterceptionContext interceptionContext)。<>c__DisplayClass1a.b__19(DbConnection conn) 在 System.Data.Entity .SqlServer.SqlProviderServices.<>c__DisplayClass33.b__32() 在 System.Data.Entity.SqlServer.DefaultSqlExecutionStrategy.<>c__DisplayClass1.b__0() 在 System.Data.Entity.SqlServer.DefaultSqlExecutionStrategy.Execute[TResult](Func 1 operation) at System.Data.Entity.SqlServer.DefaultSqlExecutionStrategy.Execute(Action operation) at System.Data.Entity.SqlServer.SqlProviderServices.UsingConnection(DbConnection sqlConnection, Action1 行为)在 System.Data.Entity.SqlServer.SqlProviderServices.UsingMasterConnection(DbConnection sqlConnection,操作1 act) at System.Data.Entity.SqlServer.SqlProviderServices.CreateDatabaseFromScript(Nullable1 commandTimeout, DbConnection sqlConnection, String createDatabaseScript) 在 System.Data.Entity.SqlServer.SqlProviderServices.DbCreateDatabase(DbConnection 连接, Nullable1 commandTimeout, StoreItemCollection storeItemCollection) at System.Data.Entity.Core.Common.DbProviderServices.CreateDatabase(DbConnection connection, Nullable1 commandTimeout, StoreItemCollection storeItemCollection) 在 System.Data.Entity.Migrations.DbMigrator System.Data.Entity.Migrations.Utilities.DatabaseCreator.Create(DbConnection 连接) 在 System.Data.Entity.Core.Objects.ObjectContext.CreateDatabase() .EnsureDatabaseExists(Action mustSucceedToKeepDatabase) 在 System.Data.Entity.Migrations.Infrastructure.MigratorBase.EnsureDatabaseExists(Action mustSucceedToKeepDatabase) 在 System.Data.Entity.Migrations.DbMigrator.Update(String targetMigration) 在 System.Data.Entity.Migrations.Infrastructure System.AppDomain.DoCallBack(CrossAppDomainDelegate callBackDelegate) System.AppDomain 的 System.Data.Entity.Migrations.Design.ToolingFacade.UpdateRunner.Run() 的 .MigratorBase.Update(String targetMigration)。DoCallBack(CrossAppDomainDelegate callBackDelegate)
在 System.Data.Entity.Migrations.Design.ToolingFacade.Run(BaseRunner runner) 在 System.Data.Entity.Migrations.Design.ToolingFacade.Update(String targetMigration, Boolean force) 在 System.Data.Entity.Migrations.UpdateDatabaseCommand。 <>c__DisplayClass2.<.ctor>b__0() at System.Data.Entity.Migrations.MigrationsDomainCommand.Execute(Action command) ClientConnectionId:23ca49c1-4797-4bc3-8f16-f34fd77f2cbe 发生文件激活错误。物理文件名“\baza.mdf”可能不正确。诊断并更正其他错误,然后重试该操作。创建数据库失败。无法创建列出的某些文件名。检查相关错误。下午>

4

3 回答 3

10

您可以在由 Enable-Migrations 命令创建的 Configuration 类中为 Update-Database 设置 DataDirectory:

internal sealed class Configuration : DbMigrationsConfiguration<DataContext>
{
    public Configuration()
    {
        AutomaticMigrationsEnabled = false;
        var dataDirPath = "<YourPath>";
        AppDomain.CurrentDomain.SetData("DataDirectory", dataDirPath);
    }
}
于 2015-08-09T18:51:12.040 回答
8

问题 1(共 2 个)

设置 的值时DataDirectory,它必须是目录,而不是文件。您正在传递absolute变量的值,即:

C:\Users\s8359_000\Documents\Visual Studio 2013\Projects\Projekt5 — kopia\Projekt5\App_Data\Cos.mdf

其中包含文件名。那是无效的。DataDirectory是一个替换值,因此指定:

AttachDbFilename=|DataDirectory|\Cos.mdf

在连接字符串中将转换为:

C:\Users\s8359_000\Documents\Visual Studio 2013\Projects\Projekt5 — kopia\Projekt5\App_Data\Cos.mdf\Cos.mdf

那不是一条有效的路径。因此,.NET 似乎认为 的值DataDirectory无效并且不使用它,因此从当前工作目录开始。

使用Path.GetDirectoryName(relative)而不是Path.GetFullPath(relative)设置值,absolute它应该可以工作,因为它将值设置DataDirectory为:

C:\Users\s8359_000\Documents\Visual Studio 2013\Projects\Projekt5 — kopia\Projekt5\App_Data

连接字符串的 MSDN 页面底部有一些其他详细信息,在标题为“支持 |DataDirectory| 替换字符串...”的部分中

问题 2(共 2 个)

  1. “DataDirectory”在 AppDomain 中设置。
  2. 控制台应用程序有自己的 AppDomains,它们在启动时创建并在退出时消失。
  3. 包管理器(您正在运行的地方Update-Database)无权访问您设置“DataDirectory”值的控制台应用程序的 AppDomain。
  4. 您需要:
    1. 在包管理器中以编程方式设置“DataDirectory”,或
    2. 在控制台应用程序的上下文中以编程方式运行“更新数据库”

我不知道如何以编程方式与包管理器交互,但我确实设法弄清楚如何以编程方式触发“更新数据库”过程。只需在设置“DataDirectory”的值后添加以下行:

Database.SetInitializer(new
    MigrateDatabaseToLatestVersion<YourDataContextName, Configuration>()
 );

您还需要至少一个(如果不是两个)using语句:

  • using System.Data.Entity;
  • using ProjectName.Migrations; // namespace of Migrations\Configuration.cs

请注意,仅此一项不会创建数据库。当您第一次通过 DbContext访问数据库时,将发布任何挂起的更改。

例子:

using System.Data.Entity;
using Projekt5.Migrations;

....

string relative = @"..\..\App_Data\Cos.mdf";
string absolute = Path.GetDirectoryName(absolute);
AppDomain.CurrentDomain.SetData("DataDirectory", absolute);
Database.SetInitializer(new
    MigrateDatabaseToLatestVersion<Projekt5Context, Configuration>()
 );
// database not created yet

using (var db = new Projekt5Context())
{
  db.Things.Add(new Thing { Name = "OMG This works!" });
  db.SaveChanges();
} 
// database CREATED!

此外,您可能需要通过包管理器调用以下命令(它不会立即对数据库执行任何操作,因此不会访问连接字符串):

Add-Migration InitialMigration

有关详细信息,请参阅Code First 迁移的 MSDN 页面。

SetInitializer一旦要调用的这行代码与 一起调用MigrateDatabaseToLatestVersion,它就会这样做:每次运行时(这就是为什么在控制台应用程序的开头完成此操作)它会同步“模型”中的任何更改(即现在编译到程序集中)和数据库,确保数据库具有最新版本。这假设任何新表都在DbContext类中表示。但是不需要运行额外的包管理器命令。

于 2015-01-04T02:54:10.973 回答
4

要将 DataDirectory 指向控制台项目和 EF 代码优先迁移下名为“AppData”的文件夹,您必须执行以下操作:

public static class AppData
{
    public static void Set()
    {
        // Set the |DataDirectory| path used in connection strings to point to the correct directory for console app and migrations
        var baseDirectory = AppDomain.CurrentDomain.BaseDirectory;
        string relative = @"..\..\App_Data\";
        string absolute = Path.GetFullPath(Path.Combine(baseDirectory, relative));
        AppDomain.CurrentDomain.SetData("DataDirectory", absolute);
    }
}

然后AppData.Set()从控制台应用程序和数据库迁移的入口点调用:

1)控制台应用程序的Main-method或Startup-class:

class Program
{
    static void Main()
    {
         AppData.Set();
    }
}

2) EF 代码首次迁移

public class DatabaseContext : DbContext
{
    // Add this constructor to your database context
    public DatabaseContext() : base()
    {
        AppData.Set();
    }

    // DbSet's are defined here
}
于 2016-05-23T06:23:14.857 回答