我尝试执行以下操作:
分离数据库
将文件复制到临时文件夹
再次附加数据库
这是第一次使用,但是当我尝试从同一个进程第二次运行此方法时,我收到错误。我总是可以访问从其他客户端再次附加的数据库,但不能从我的应用程序中访问。
错误是:
“尝试将请求发送到服务器时传输级别错误。(提供程序:共享内存提供程序,错误:0 - 管道另一端没有进程。)”,当我尝试从sys读取数据时新附加数据库的.database_files。
该错误是由德语“FehleraufÜbertragungsebenebeim Senden der Anforderung an den Server”翻译而来。
它发生在“cmdGetDBFileName.ExecuteReader”之后。我仍然可以打开连接,但查询sys.database_files failes。
源代码很长,但我想你可以在开始时跳过这部分,我将db的文件名分开。你看到我的错误或有任何想法我可以检查吗?
public bool DetachB2CPrepare()
{
_log.Debug("DetachB2CPrepare");
SqlConnection prepareDBConnection = null;
SqlConnection prepareMasterDBConnection = null;
SqlDataReader readerDbFiles = null;
bool result = true;
try
{
//rc_b2c_product_prepare.mdf
string prepareDBPysicalFileName = "";
//rc_b2c_product_prepare
string prepareDBFileName = "";
//D:\Program Files\Microsoft SQL Server\MSSQL10.MSSQLSERVER\MSSQL\DATA\rc_b2c_product_prepare.mdf
string prepareDBFileNameComplete = "";
//rc_b2c_product_prepare_1.ldf
string prepareTransactionLogPhysicalFileName = "";
//rc_b2c_product_prepare_log
string prepareTransactionLogFileName = "";
//D:\Program Files\Microsoft SQL Server\MSSQL10.MSSQLSERVER\MSSQL\DATA\rc_b2c_product_prepare_1.ldf
string prepareTransactionLogFileNameComplete = "";
_log.DebugFormat("Try to open B2CPrepare");
prepareDBConnection = new SqlConnection(ConfigurationManager.ConnectionStrings["B2CPrepare"].ConnectionString);
prepareDBConnection.Open();
//Get the file names of DB
SqlCommand cmdGetDBFileName = new SqlCommand("select name , physical_name, type from sys.database_files where type= 0");
cmdGetDBFileName.Connection = prepareDBConnection;
readerDbFiles = cmdGetDBFileName.ExecuteReader();
if (readerDbFiles.Read())
{
prepareDBFileName = (string)readerDbFiles["name"];
prepareDBFileNameComplete = (string)readerDbFiles["physical_name"];
int lastSlash = prepareDBFileNameComplete.LastIndexOf(@"\");
prepareDBPysicalFileName = prepareDBFileNameComplete.Substring(lastSlash + 1, prepareDBFileNameComplete.Length - lastSlash - 1);
readerDbFiles.Close();
}
else{
return false;
}
cmdGetDBFileName.CommandText = "select name , physical_name, type from sys.database_files where type= 1";
readerDbFiles = cmdGetDBFileName.ExecuteReader();
if (readerDbFiles.Read())
{
prepareTransactionLogFileName = (string)readerDbFiles["name"];
prepareTransactionLogFileNameComplete = (string)readerDbFiles["physical_name"];
int lastSlash = prepareTransactionLogFileNameComplete.LastIndexOf(@"\");
prepareTransactionLogPhysicalFileName = prepareTransactionLogFileNameComplete.Substring(lastSlash + 1, prepareTransactionLogFileNameComplete.Length - lastSlash - 1);
readerDbFiles.Close();
}
else
{
return false;
}
_log.DebugFormat("shrink transactionlog {0}", prepareTransactionLogFileName);
SqlCommand cmdShrinkPrepare = new SqlCommand(string.Format(@"DBCC Shrinkfile('{0}',100) ", prepareTransactionLogFileName));
cmdShrinkPrepare.Connection = prepareDBConnection;
cmdShrinkPrepare.ExecuteNonQuery();
//master auf MyProductName
prepareMasterDBConnection = new SqlConnection(ConfigurationManager.ConnectionStrings["MyProductNameMaster"].ConnectionString);
prepareMasterDBConnection.Open();
_log.Debug("cmdOffline");
//Datenbank verbindunge löschen
SqlCommand cmdOffline = new SqlCommand(@"ALTER DATABASE rc_b2c_product_prepare SET SINGLE_USER WITH ROLLBACK IMMEDIATE");
cmdOffline.Connection = prepareMasterDBConnection;
cmdOffline.ExecuteNonQuery();
_log.Debug("cmdDetach: rc_b2c_product_prepare" );
SqlCommand cmdDetach = new SqlCommand(@"dbo.sp_detach_db @dbname = N'rc_b2c_product_prepare',@keepfulltextindexfile = N'false'");
cmdDetach.Connection = prepareMasterDBConnection;
cmdDetach.ExecuteNonQuery();
string pathForCopies = MyProductName.Backend.settings.B2CPrepareDBBackupPath;
//copy files to temp folder
string tempFileDB = pathForCopies + "\\" + prepareDBPysicalFileName;
string tempFileLog = pathForCopies + "\\" + prepareTransactionLogPhysicalFileName;
_log.DebugFormat("Copy: {0} TO: {1}", prepareDBFileNameComplete, tempFileDB);
System.IO.File.Copy(prepareDBFileNameComplete, tempFileDB, true);
_log.DebugFormat("Copy: {0} TO: {1}", prepareTransactionLogFileNameComplete, tempFileLog);
System.IO.File.Copy(prepareTransactionLogFileNameComplete, tempFileLog, true);
_log.DebugFormat("cmdAttach: db {0} log {1}", prepareDBFileNameComplete, prepareTransactionLogFileNameComplete);
SqlCommand cmdAttach = new SqlCommand(
string.Format(@"
CREATE DATABASE rc_b2c_product_prepare ON
( FILENAME = N'{0}' ),
( FILENAME = N'{1}' )
FOR ATTACH", prepareDBFileNameComplete, prepareTransactionLogFileNameComplete));
cmdAttach.Connection = prepareMasterDBConnection;
cmdAttach.ExecuteNonQuery();
_log.Debug("ALTER DATABASE rc_b2c_product_prepare SET MULTI_USER ");
//set multi user
SqlCommand cmdOnline = new SqlCommand(@"ALTER DATABASE rc_b2c_product_prepare SET MULTI_USER WITH ROLLBACK IMMEDIATE");
cmdOnline.Connection = prepareMasterDBConnection;
cmdOnline.ExecuteNonQuery();
return result;
}
catch (Exception e)
{
_log.Error(e);
return false;
}
finally
{
if (prepareDBConnection != null)
{
prepareDBConnection.Close();
}
if (prepareMasterDBConnection != null)
{
prepareMasterDBConnection.Close();
}
if (readerDbFiles != null)
{
readerDbFiles.Close();
}
}
}
答案 0 :(得分:1)
可能是连接池的问题,您是否尝试在执行分离/附加之前关闭prepareDBConnection
?
其次,你看过SQL管理对象(SMO) - 这是一个example for the detach/attach。
很明显,当您只想制作备份副本时,不必分离数据库,而是可以将其设置为脱机。 Using SMO或using SQL(sp_dboption doc)。
答案 1 :(得分:1)
听起来它可能与尝试使用由于连接池而不再有效的连接有关。
您可以尝试关闭连接池以查看是否存在问题。为此,请在配置文件中的SQL连接字符串中添加“Pooling = false”。
答案 2 :(得分:0)
分离MSSQL数据库
USE master;
GO
ALTER DATABASE [AdventureWorks2012] SET SINGLE_USER WITH ROLLBACK IMMEDIATE;
EXEC sp_detach_db @dbname = N'AdventureWorks2012';
GO
附加分离的数据库
USE master;
GO
CREATE DATABASE MyAdventureWorks
ON (FILENAME = 'C:\MySQLServer\AdventureWorks2012_Data.mdf'),
(FILENAME = 'C:\MySQLServer\AdventureWorks2012_Log.ldf')
FOR ATTACH;
GO
我为多个数据库尝试了这个代码,它工作正常。