【问题标题】:How to Detach a database so that it could be copied/moved?如何分离数据库以便可以复制/移动它?
【发布时间】:2014-12-20 09:54:29
【问题描述】:

我使用 Database first EF 方法在使用 C# 的 wpf 应用程序中创建模型。添加相关信息、更改列名、表名后,我想将其复制到新位置。但我收到数据库正在使用的错误消息。

using (var ctx = new TableGraphDBEntities())
{
    for (int l = 0, m = 1; l < TableNames.Count; l++, m++)
    {
        string columnxQ = "sp_rename 'Table1.x','" + XNames[l] + "', 'COLUMN'";
        string columnyQ = "sp_rename 'Table1.y','" + YNames[l] + "', 'COLUMN'";
        string talbeQ = "sp_rename Table" + m.ToString() + "," + TableNames[l];
        string detachQ = "sp_detach_db @dbname = N'TableGraphDB'";
        //string setOffline = "
        //string detachQ = "USE master; GO EXEC sp_detach_db @dbname = N'TableGraphDB'; GO";
        ctx.Database.ExecuteSqlCommand(columnxQ);
        ctx.Database.ExecuteSqlCommand(columnyQ);
        ctx.Database.ExecuteSqlCommand(talbeQ);
        ctx.Database.ExecuteSqlCommand(detachQ);


    }     
}
string oldFilePath = System.AppDomain.CurrentDomain.BaseDirectory + "TableGraphDB.mdf";
string FilePath = Properties.Settings.Default.ExtensionFileDir + @"\Saved DataBases\" + fnw.FileName + ".mdf";
if (File.Exists(FilePath))
{
    MessageBox.Show("The database aleady exist, please type a different name");
    return;
}
//FileInfo fileInfo = new FileInfo(oldFilePath);
//while (IsFileLocked(fileInfo))
//{

//}
File.Copy(oldFilePath, FilePath);
MessageBox.Show("Database is saved!");

这里是 slq 命令http://msdn.microsoft.com/en-gb/library/ms187858.aspx的链接

数据库位于 Bin 文件夹中。每次运行应用程序时,它都会从项目中复制为新副本。如果我关闭应用程序并重新打开它,它可以与所有数据一起复制。

我尝试使用 ExecuteSqlCommand(),但没有帮助。 那么我如何分离数据库以便移动/复制它?

不幸的是 StackOverFlow 不允许我回答我自己的问题,所以我必须在这里写下来。

答案: 首先,您必须检查数据库的实际名称,它不一定是数据库文件的名称。为此,您需要:

  1. 在 Visual Studio 或 SQL Management Studio 中打开服务器资源管理器。
  2. 打开新查询。
  3. 执行以下查询:SELECT name, create_date FROM sys.databases
  4. 检查数据库的名称(在我的例子中,它是数据库文件的完整路径,它可以只是数据库的名称或其他任何名称。)

然后你可以通过执行以下代码来更改列和表的名称:

using (var ctx = new TableGraphDBEntities())
{
    for (int l = 0, m = 1; l < TableNames.Count; l++, m++)
    {
        string columnxQ = "sp_rename 'Table1.x','" + XNames[l] + "', 'COLUMN'";
        string columnyQ = "sp_rename 'Table1.y','" + YNames[l] + "', 'COLUMN'";
        string talbeQ = "sp_rename Table" + m.ToString() + "," + TableNames[l];
        ctx.Database.ExecuteSqlCommand(columnxQ);
        ctx.Database.ExecuteSqlCommand(columnyQ);
        ctx.Database.ExecuteSqlCommand(talbeQ);
        ctx.Dispose();
    }
}

最后使用以下代码将其分离并移动到新位置:

string oldFilePath = System.AppDomain.CurrentDomain.BaseDirectory + "TableGraphDB.mdf";
string conString = @"Data Source=(LocalDB)\v11.0;Integrated Security=True;";
using (System.Data.SqlClient.SqlConnection con = new System.Data.SqlClient.SqlConnection(conString))
{
    string query = @"USE [master] 
        ALTER DATABASE ["+oldFilePath+@"] SET  SINGLE_USER WITH ROLLBACK IMMEDIATE
        USE [master] 
        EXEC master.dbo.sp_detach_db @dbname = N'"+oldFilePath+"'";
    SqlCommand cmd = new SqlCommand(query, con);
    con.Open();
    cmd.ExecuteNonQuery();
    cmd.Dispose();
    con.Dispose();
}

string FilePath = Properties.Settings.Default.ExtensionFileDir + @"\Saved DataBases\" + fnw.FileName + ".mdf";
if (File.Exists(FilePath))
{
    MessageBox.Show("The database aleady exist, please type a different name");
    return;
}
File.Copy(oldFilePath, FilePath);

注意:如果你尝试实现 ctx.Database.ExecuteSqlCommand(query),你会得到如下错误:

多语句事务中不允许使用 ALTER DATABASE 语句。 不能在事务中执行过程“sys.sp_detach_db”。 将数据库上下文更改为“主”。

【问题讨论】:

    标签: c# sql-server wpf entity-framework-6 localdb


    【解决方案1】:

    如果您使用的是 EF6,您可以尝试以下代码:

    string command = "EXEC sp_detach_db 'TableGraphDB', 'true'";
    dbContext.ExecuteStoreCommand(command);
    

    sp_detach_db 过程中的第二个参数将断开与该数据库的所有连接

    【讨论】:

    • 我之前试过。由于某种原因,它无法识别我的数据库!
    • 你的第二行写错了,应该使用ctx.Database.ExecuteSqlCommand(command);
    【解决方案2】:

    在 SSMS 中,这是用于分离数据库的查询。 你可以试试这个吗?

    你应该能够将整个事情包装成一个字符串并执行它。 我不确定它是否会对“GO”感到满意,因此您可能必须删除它们。

    string detachQ = "" + 
    "USE [master]\n" +
    "GO\n" +
    "ALTER DATABASE [TableGraphDB] SET  SINGLE_USER WITH ROLLBACK IMMEDIATE\n" +
    "GO\n" +
    "USE [master]\n" +
    "GO\n" +
    "EXEC master.dbo.sp_detach_db @dbname = N'TableGraphDB'\n" +
    "GO\n";
    
    ctx.Database.ExecuteSqlCommand(detachQ);
    

    【讨论】:

    • 如何在 ctx.Database.ExecuteSqlCommand(detachQ); 中使用它或者我可以在运行时分离数据库的任何其他方式?
    • 使用 Go 时出现语法错误。当我删除 Go 时,我收到以下错误:多语句事务中不允许使用 ALTER DATABASE 语句。 2. 数据库“TableGraphDB”不存在。提供一个有效的数据库名称。要查看可用的数据库,请使用 sys.databases。 3. 将数据库上下文更改为“master”。
    • 因此您可能必须拆分查询并调用 execute 2 次。一次改变,一次分离
    • 我拆分了它,但在第一次执行时我仍然遇到相同的错误:即 - 多语句事务中不允许使用 ALTER DATABASE 语句。将数据库上下文更改为“主”。
    • 您是否正在连接到您要分离的数据库?您应该连接到 master。
    猜你喜欢
    • 2023-03-09
    • 2021-07-25
    • 1970-01-01
    • 2010-11-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-10-19
    • 2011-08-13
    相关资源
    最近更新 更多