数据库正被另一个进程使用……但是什么进程?

我编写了一个非常小的C#程序,它使用一个非常小的SQL Server数据库,纯粹用于一些学习和测试目的。 数据库用于这个新项目,而不是其他任何地方。 但是,我在运行程序无法运行的Debugs时遇到问题,因为数据库“正由另一个进程使用”。

如果我重新启动我的机器,它将再次工作,然后经过几次测试运行后,我将再次遇到同样的问题。

我发现在互联网上报告了许多类似的问题,但是没有找到关于如何解决这个问题的明确答案。 首先,我如何找出使用我的.mdf和.ldf文件的“其他进程”? 然后,如何释放这些文件而不是为了在一段时间后停止这种发生的时间而不被保留?!?

我是VS2010,SQL Server和C#的新手,所以请在你给我的任何回复中描述一下!

这是我的代码,正如你所看到的,你无法获得更基本的东西,我当然不应该遇到这么多问题!

namespace MySqlTest { public partial class Form1 : Form { SqlConnection myDB = new SqlConnection(@"Data Source=MEDESKTOP;AttachDbFilename=|DataDirectory|\SqlTestDB.mdf;Initial Catalog=MySqlDB;Integrated Security=True"); SqlDataAdapter myDA = new SqlDataAdapter(); SqlCommand mySqlCmd = new SqlCommand(); string mySQLcmd; int myCount; public Form1() { InitializeComponent(); } private void button1_Click(object sender, EventArgs e) { MessageBox.Show("myDB state = " + myDB.State.ToString()); //Open SQL File myDB.Open(); MessageBox.Show("myDB state = " + myDB.State.ToString()); } private void button2_Click(object sender, EventArgs e) { myCount++; MessageBox.Show("myCount = " + myCount.ToString()); //Insert Record Into SQL File mySqlCmd.Connection = myDB; mySqlCmd.CommandText = "INSERT INTO Parent(ParentName) Values(myCount)"; myDA = new SqlDataAdapter(mySqlCmd); mySqlCmd.ExecuteNonQuery(); } private void button3_Click(object sender, EventArgs e) { //Read Record From SQL File } private void button4_Click(object sender, EventArgs e) { //Read All Records From SQL File } private void button5_Click(object sender, EventArgs e) { //Delete Record From DQL File } private void button6_Click(object sender, EventArgs e) { MessageBox.Show("myDB state = " + myDB.State.ToString()); //Close SQL File myDB.Close(); MessageBox.Show("myDB state = " + myDB.State.ToString()); } private void button7_Click(object sender, EventArgs e) { //Quit this.Close(); } } } 

最可能的选择:

  1. 您程序的先前(崩溃)实例
  2. Visual Studio(打开表设计器或类似的东西)

您可以通过查看服务器资源管理器来检查1)与TaskManager和2)。 您的数据库应显示一个小红叉,表示“已关闭”。

您应该尽快重写代码以关闭连接。 使用try / finally或using(){ }块。

这是使用“ Using ”语句重写的代码。 当我执行程序并单击Insert Record Into SQL File时,关闭它,用myCount = 1完成该过程(虽然我不是100%确定它实际上正在进行物理写入,但是我错过了一个实际的命令“提交”更新?!?)并重新显示表单。

如果我再次单击“将记录插入SQL文件”,则会出现如下错误:

SqlException未处理

无法打开用户默认数据库。 登录失败。 用户’MEDESKTOP \ Gary’登录失败。

这是程序(我是这台PC上唯一的用户,拥有完整的Admin权限,此时数据库的“状态”是,根据Properties,Closed,所以它看起来像第一次通过代码那样做了期待……

 using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Linq; using System.Text; using System.Windows.Forms; using System.Data.SqlClient; namespace MySqlTest { public partial class Form1 : Form { int myCount; string myDBlocation = @"Data Source=MEDESKTOP;AttachDbFilename=|DataDirectory|\mySQLtest.mdf;Integrated Security=True;User Instance=False"; public Form1() { InitializeComponent(); } private void button2_Click(object sender, EventArgs e) { myCount++; MessageBox.Show("myCount = " + myCount.ToString()); //Insert Record Into SQL File myDB_Insert(); } private void button3_Click(object sender, EventArgs e) { //Read Record From SQL File } private void button4_Click(object sender, EventArgs e) { //Read All Records From SQL File } private void button5_Click(object sender, EventArgs e) { //Delete Record From SQL File } private void button7_Click(object sender, EventArgs e) { //Quit myDB_Close(); this.Close(); } private void Form1_Load(object sender, EventArgs e) { } private void Form1_Close(object sender, EventArgs e) { } void myDB_Insert() { using (SqlConnection myDB = new SqlConnection(myDBlocation)) using (SqlCommand mySqlCmd = myDB.CreateCommand()) { myDB.Open(); **<<< Program fails here, 2nd time through** mySqlCmd.CommandText = "INSERT INTO Parent (ParentName) VALUES(@ParentNameValue)"; mySqlCmd.Parameters.AddWithValue("@ParentNameValue", myCount); mySqlCmd.ExecuteNonQuery(); myDB.Close(); } return; } void myDB_Close() { using (SqlConnection myDB = new SqlConnection(myDBlocation)) using (SqlCommand mySqlCmd = new SqlCommand()) { myDB.Close(); } return; } } } 

我不明白为什么我突然失去了对我已经使用的文件的访问权限?!?

尝试运行sp_who2以查看进程列表。

仅供参考:您无需重启机器,最糟糕的情况下,重启SQL Server服务

IIRC使用AttachDbFilename旋转在您的进程正在使用的用户帐户下运行的SqlServr.exe进程,与作为服务运行的SqlServer实例分开(因此停止MsSqlServer服务不会停止此问题)。 在出口脏的情况下,有时这个过程不会被清理干净。 我怀疑杀死这个进程将释放db文件。

尝试使用Microsoft的技术研究员Mark Russinovich编写的Process Explorer 。 它是Windows管理员/开发人员口袋中的标准瑞士军队工具。 它可以显示哪些进程持有系统资源的句柄。

安装Process Explorer后,请尝试以下操作:

  1. 让您的系统进入故障状态(这样运行程序不起作用)。
  2. 启动Process Explorer(您需要成为管理员才能充分利用其function)。
  3. 单击顶部菜单栏中的“查找”,然后键入.mdf或.ldf文件的名称。

搜索结果应显示一个进程/服务,其中一个资源仍由错误终止的进程保留。

使用SQL Server使用VS 2010和entity framework我已经遇到过这种情况了好几次。 在我的情况下,它发生在我尝试运行程序时,我在服务器资源管理器中打开了一个查询。 一旦失败,我不得不放弃所有连接以使其再次工作。

VS2010将您在Server Explorer中使用的源数据库( .MDF.LDF文件)复制到项目调试文件夹。 这是您在运行时使用的副本。 复制此文件时,MDF属性控制默认情况下Copy to Output Directory ,它将设置为Copy always 。 这意味着它将尝试在新的构建或运行时复制该文件,如果您在其他地方打开它会失败,然后它会挂起。

查看连接的方法是打开SQL Server管理控制台。 默认情况下,VS2010使用连接字符串中指定的SQL Server用户实例。 在entity framework的情况下,它在App.Config XML中。

用户实例是SQL Server的内存副本,具有分配给登录用户的所有用户权限。 要找到它,你需要找到正确的连接。

从SQL的主实例运行此查询将显示所有用户实例连接。

 SELECT owning_principal_name, instance_pipe_name, heart_beat FROM sys.dm_os_child_instances 

这将返回如下所示的内容:

  |owning_principle_name | instance_pipe_name | heart_beat -------------------------------------------------------------------------------- 1 | MyServer\Admin | \\.\pipe\91B3063E-CD0F-4B\tsql\query\ | dead -------------------------------------------------------------------------------- 2 | MyServer\Rich | \\.\pipe\B04A1D3B-6268-49\tsql\query\ | alive 

如果复制实例名称并将其用作新连接中的服务器名称,则以与其关联的用户身份运行,您将从调试文件夹中看到您的数据。

现在,如果右键单击数据库并选择“ Tasks > Detach... ”,将打开“ Detach Database对话框,选中数据库文件名旁边的“ Drop Connections复选框,然后单击“ OK

数据库将从列表中删除,您应该能够构建并运行您的应用程序。

我在以下url找到了这个解决方案: http : //oreilly.com/catalog/errata.csp?isbn = 0636920022220

右键单击VS数据库资源管理器中的数据库,然后单击调试会话之间的关闭连接,它对我有用。

最简单的是去Server Explorer。 选择问题数据库。 右键单击并选择“关闭连接”。

如果已关闭,请连接并断开连接。

我认为已经附加了SqlTestDB.mdf。 我以前遇到过这个问题,只需转到Ms Sql server并分离数据库,然后在Visual Studio的Server Explorer中重建连接。

您在开始时打开dbase,并且在完成时无法确定它是否正在发布。 你真的在等待内存管理器对其进行排序,这取决于系统在何时释放文件时的繁忙程度。

我认为您需要将其更改为“需要时打开”。

例如,我将代码放入其自己的类中的任何数据库,一旦操作完成,我就发布它。

打开和关闭确实有开销,但我发现通过执行以下操作我可以忍受它,

在您的类中有多个入口点,一个用于单个事务,另一个用于多个事务。 例如

  S_UpdateSingleRecord(...) M_UpdateManyRecords(...) 

我发现在大多数应用程序中,这些都可以是静态的,因为它们本身并不存储数据,只能将数据传递给数据库或从数据库传递数据。 如果我想为我的应用程序缓存一些内容,它只会丢失它的静态状态。

我在S_SingleTransaction()中使用’using’,因为它为我清理它。 但是当我的调用函数完成时,我将多个入口点打开并关闭它。 我从未遇到过单个mdf和一个应用程序的锁定问题。 它将重新使用一个mdf和多个应用程序,在这些情况下,您需要使用MSSQL作为服务dbase,您会发现它在Visual Studio中设置同样容易,然后在其他应用程序中已经在工具栏的列表中有该数据库。