如何在代码中分离LocalDB(SQL Server Express)文件

时间:2013-04-26 19:28:13

标签: localdb

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

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

3 个答案:

答案 0 :(得分:10)

我不得不把几个地方的答案串起来,所以我会在这里发布: 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

答案 1 :(得分:10)

我有同样的问题,正在考虑如何处理它。

有两种方法。

(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):Database&#39; c:\ blablabla \ database1.mdf&#39;已经存在。选择其他数据库名称。

如果数据库文件被删除并且您尝试以编程方式创建

,则会发生

// DataContext
if (!DatabaseExists())
    CreateDatabase();

另一种方式

您还可以像这样运行命令行工具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 的应用程序,那么下次尝试进行查询时会遇到附加延迟。

答案 2 :(得分:1)

这是我的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}'");
}