在部署中使用 LocalDB .mdf 文件时,您通常需要移动、删除或备份数据库文件。首先分离这个文件是最重要的,因为简单地删除它会导致错误,因为 LocalDB 仍然保留它的注册。
那么如何在代码中分离 LocalDB .mdf 文件呢?
在部署中使用 LocalDB .mdf 文件时,您通常需要移动、删除或备份数据库文件。首先分离这个文件是最重要的,因为简单地删除它会导致错误,因为 LocalDB 仍然保留它的注册。
那么如何在代码中分离 LocalDB .mdf 文件呢?
我有同样的问题,正在考虑如何处理它。
有3种方法。
在使用数据库结束时(或期间)分离
我没有找到在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
之后没有任何东西会尝试查询(或者你再次附加它)。
开始时分离
在与 建立任何连接之前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();
另一种方式
您还可以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,那么他们下次尝试进行查询时会遇到附加延迟。
我不得不将几个地方的答案串在一起,所以我将在此处发布: 请注意,在通过 SQL Server 对象资源管理器进行分离之前手动删除 .mdf 文件后,可以手动从 Visual Studio 中分离它。
''' <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
这是我的 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}'");
}