C# 分离本地数据库.mdf,复制,附加新文件

C# 分离本地数据库.mdf,复制,附加新文件,c#,sql-server,local,detach,C#,Sql Server,Local,Detach,我尝试分离本地数据库。mdf将其复制到另一个文件夹中,并在启动时附加新文件,在关闭时复制到旧文件夹 它似乎在启动时起作用,但在关闭表单时出现错误: 进程无法访问文件“C:\ProgramData\MyData\db1.mdf”,因为其他进程正在使用该文件 这是我的密码: public Form() { InitializeComponent(); DetachDatabase(); CopyDb(); AttachD

我尝试分离本地数据库。mdf将其复制到另一个文件夹中,并在启动时附加新文件,在关闭时复制到旧文件夹

它似乎在启动时起作用,但在关闭表单时出现错误:

进程无法访问文件“C:\ProgramData\MyData\db1.mdf”,因为其他进程正在使用该文件

这是我的密码:

    public Form()
    {
        InitializeComponent();
        DetachDatabase();
        CopyDb();
        AttachDatabase();
        AppDomain.CurrentDomain.SetData("DataDirectory", Data.MyNewFolder);    
    }


    public static bool DetachDatabase()
    {
        try
        {

            string connectionString = String.Format(@"Data Source=(LocalDB)\v11.0;Initial Catalog=master;Integrated Security=True");
            using (var cn = new SqlConnection(connectionString))
            {
                cn.Open();
                SqlCommand cmd = cn.CreateCommand();
                cmd.CommandText = String.Format("exec sp_detach_db '{0}'", "db1");
                cmd.ExecuteNonQuery();
                cmd.CommandText = String.Format("exec sp_detach_db '{0}'", "db2");
                cmd.ExecuteNonQuery();
                return true;
            } 
        }
        catch
        {
            return false;
        }
    }

    public static bool AttachDatabase()
    {
        try
        {
            string connectionString = String.Format(@"Data Source=(LocalDB)\v11.0;Initial Catalog=master;Integrated Security=True");
            using (var cn = new SqlConnection(connectionString))
            {
                cn.Open();
                SqlCommand cmd = cn.CreateCommand();
                cmd.CommandText = String.Format("exec sys.sp_attach_db    db1,    'db1.mdf'");
                cmd.CommandText = String.Format("exec sys.sp_attach_db    db2,    'db2.mdf'");
                cmd.ExecuteNonQuery();
                return true;
            }
        }
        catch
        {
            return false;
        }
    }

    private void Frm_FormClosing(object sender, FormClosingEventArgs e)
    {
        LocalDB.DetachDatabase();
        CopyDb();
        LocalDB.AttachDatabase();
    }
做这件事的好方法是什么


谢谢

您需要切换到
master
并将目标数据库脱机

警告:自担风险使用(例如,您是否可以将
与立即回滚一起使用
?)

sp_detach_db
的第二个参数只是避免了统计数据更新(会更快)

现在,您可以安全地将
mdf
ldf
文件从其原始位置移动

假设您的数据库已经脱机,并且您已将
db1.mdf
文件移动到
D:\which
,我认为您可以做到这一点(我没有测试它,当心


SQL Server是一个基于服务器的数据库系统-因此最好的方法是不要摆弄
.mdf
文件,只需将数据库留在服务器上,连接到它并使用它来关闭数据库。数据库仍然连接在一起,但我找到了执行此操作的方法var start=new ProcessStartInfo(“sqllocaldb”,“stop MSSQLLocalDB”);start.WindowStyle=ProcessWindowStyle.Hidden;使用(var stop=Process.Start(Start))stop.WaitForExit();start.Arguments=“删除MSSQLLocalDB”;使用(var delete=Process.Start(Start))delete.WaitForExit();我想知道是否没有办法在呼叫返回之前强制DB完全分离(例如,设置单用户模式,重新连接后返回多用户模式)。重新启动流程感觉不是正确的做法,但是,嗯…:另外,如果这是您的主表单,为什么不在表单完全销毁后(以及在构建之前)分离/附加表单,而不是使用事件处理程序?
var commandText = string.Format(@"
    USE MASTER;
    ALTER DATABASE {0} SET OFFLINE WITH ROLLBACK IMMEDIATE;
    EXEC sp_detach_db '{0}', 'true';", "db1");
var commandText = string.Format(@"
    USE MASTER;
    ALTER DATABASE {0}
      MODIFY FILE (
        NAME = '{0}',
        FILENAME = 'D:\Wherever\{0}.mdf');
    ALTER DATABASE {0} SET ONLINE;", "db1");