【问题标题】:How to detach a LocalDB (SQL Server Express) file in code如何在代码中分离 LocalDB (SQL Server Express) 文件
【发布时间】:2013-04-26 19:28:13
【问题描述】:

在部署中使用 LocalDB .mdf 文件时,您通常需要移动、删除或备份数据库文件。 首先将此文件分离为simply deleting it will cause errors because LocalDB still keeps a registration of it 至关重要。

那么如何在代码中分离 LocalDB .mdf 文件?

【问题讨论】:

    标签: localdb


    【解决方案1】:

    我遇到了同样的问题,正在考虑如何处理。

    有 3 种方法。

    1. 在使用数据库结束时(或期间)分离

      我在LinqToSQL中没有找到关闭连接的方法,但实际上不需要。只需执行以下代码:

       var db = @"c:\blablabla\database1.mdf";
       using (var master = new DataContext(@"Data Source=(LocalDB)\v11.0;Initial Catalog=master;Integrated Security=True"))
       {
           master.ExecuteCommand(@"ALTER DATABASE [{0}] SET OFFLINE WITH ROLLBACK IMMEDIATE", db);
           master.ExecuteCommand(@"exec sp_detach_db '{0}'", db);
       }
      

      并确保之后没有任何东西会尝试查询db(或者你再次附加它)。

    2. 在开始时分离

      在您与db 建立任何连接之前,分离很简单:

       var db = @"c:\blablabla\database1.mdf";
       using (var master = new DataContext(@"Data Source=(LocalDB)\v11.0;Initial Catalog=master;Integrated Security=True"))
           master.ExecuteCommand(@"exec sp_detach_db '{0}'", db);
      

      这非常适合我的需求,因为我不关心启动应用程序的延迟(因为在这种情况下我必须始终附加到db),但它可以解决任何类型的问题

      System.Data.SqlClient.SqlException (0x80131904):数据库 'c:\blablabla\database1.mdf' 已存在。选择一个不同的数据库名称。

      如果数据库文件被删除并且您尝试以编程方式创建它,则会发生这种情况

       // DataContext
       if (!DatabaseExists())
           CreateDatabase();
      
    3. 另一种方式

      你也可以像这样运行命令行工具sqllocaldb

       var start = new ProcessStartInfo("sqllocaldb", "stop v11.0");
       start.WindowStyle = ProcessWindowStyle.Hidden;
       using (var stop = Process.Start(start))
           stop.WaitForExit();
       start.Arguments = "delete v11.0";
       using (var delete = Process.Start(start))
           delete.WaitForExit();
      

      它将停止服务器,分离所有数据库。如果您有其他应用程序使用 LocalDB,那么他们下次尝试进行查询时会遇到附加延迟。

    【讨论】:

    • 对于“启动时分离”,我收到:“用户无权更改数据库 '@p0',数据库不存在,或者数据库未处于允许访问检查的状态。 ALTER DATABASE 语句失败。”有什么想法吗?
    • @fschricker,是的。您没有在开始时分离。数据库已在您的应用程序中的某个位置打开。
    • 我在单元测试 [ClassInitialize] 中运行代码,所以我假设数据库已关闭(仅供参考:使用 sqllocaldb 工作正常)。但我正在通过 MS SQL Server Mgmt Studio 观看localdb;也许那个工具有一个开放的连接?
    【解决方案2】:

    我不得不将几个地方的答案串起来,所以我将在此处发布: Mind, manually detaching the .mdf file from Visual Studio is possible after manually deleting it before detachment by going through SQL Server Object Explorer.

    ''' <summary>
    ''' Detach a database from LocalDB. This MUST be done prior to deleting it. It must also be done after a inadvertent (or ill advised) manual delete.
    ''' </summary>
    ''' <param name="dbName">The NAME of the database, not its filename.</param>
    ''' <remarks></remarks>
    Private Sub DetachDatabase(dbName As String)
        Try
            'Close the connection to the database.
            myViewModel.CloseDatabase()
    
            'Connect to the MASTER database in order to excute the detach command on it.
            Dim connectionString = String.Format("Data Source=(LocalDB)\v11.0;Initial Catalog=master;Integrated Security=True")
            Using connection As New SqlConnection(connectionString)
                connection.Open()
                Dim cmd = connection.CreateCommand
                '--Before the database file can be detached from code the workaround below has to be applied.
                'http://web.archive.org/web/20130429051616/http://gunnalag.wordpress.com/2012/02/27/fix-cannot-detach-the-database-dbname-because-it-is-currently-in-use-microsoft-sql-server-error-3703
                cmd.CommandText = String.Format("ALTER DATABASE [{0}] SET OFFLINE WITH ROLLBACK IMMEDIATE", dbName)
                cmd.ExecuteNonQuery()
                '--
                '--Now detach
                cmd.CommandText = String.Format("exec sp_detach_db '{0}'", dbName)
                cmd.ExecuteNonQuery()
                '--
            End Using
        Catch ex As Exception
            'Do something meaningful here.    
        End Try
    End Sub
    

    【讨论】:

      【解决方案3】:

      这是我的 EntityFramework Core 1.0 解决方案

      如您所见,数据库名称可以与其完整文件路径一起使用。

      var dbf = fileDlg.FileName;
      var options = new DbContextOptionsBuilder();
      options.UseSqlServer($@"Server=(localdb)\mssqllocaldb;Initial Catalog=master;MultipleActiveResultSets=False;Integrated Security=True");
      using (var master = new DbContext(options.Options))
      {
           master.Database.ExecuteSqlCommand($"ALTER DATABASE [{dbf}] SET OFFLINE WITH ROLLBACK IMMEDIATE");
           master.Database.ExecuteSqlCommand($"exec sp_detach_db '{dbf}'");
      }
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2015-01-27
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多