另一个进程正在使用数据库..但过程是什么
本文关键字:数据库 过程 是什么 进程 另一个 | 更新日期: 2023-09-27 18:23:42
我写了一个非常小的C#程序,它使用了一个很小的SQL Server数据库,纯粹是为了学习&测试目的。这个数据库在这个新项目中使用,其他地方都没有。然而,我在运行调试时遇到了问题,因为数据库"正在被另一个进程使用",所以程序无法运行。
如果我重新启动我的机器,它会再次工作,然后在几次测试运行后,我会再次遇到同样的问题。
我在互联网上发现了很多类似的问题,但对于如何解决这个问题,我找不到确切的答案。首先,我如何发现"其他进程"正在使用我的.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();
}
}
}
最可能的选项:
- 程序的上一个(崩溃的)实例
- Visual Studio(打开了表设计器或类似程序)
您可以1)使用TaskManager进行检查,2)通过查看服务器资源管理器进行检查。你的数据库应该显示一个小的红十字,意思是"关闭"。
您应该重写代码以尽快关闭连接。使用try/finaly或using(){ }
块。
这是使用"using"语句重写的代码。当我执行该程序并单击"将记录插入SQL文件"时,它会关闭,以myCount=1完成该过程(尽管我不能100%确定它是否真的在进行物理写入,但我是否缺少一个真正"提交"更新的命令?!?),并重新显示Form。
如果我再次单击"将记录插入SQL文件",我会得到如下错误:
SqlException未处理
无法打开用户默认数据库。登录失败。用户登录失败"MEDESKTOP''Gary"。
这是程序(我是这台电脑上唯一的用户,拥有完全的管理员权限,此时数据库的"状态"是,根据属性,已关闭,所以它看起来像是第一次通过代码做了预期…
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查看进程列表。
仅供参考:您不需要重新启动计算机,在最坏的情况下,使用AttachDbFilename
重新启动SQL Server服务
IIRC会启动在您的进程使用的用户帐户下运行的SqlServr.exe
进程,与作为服务运行的SQL Server实例分离(因此停止MsSqlServer服务不会停止此问题)。在出口脏的情况下,有时这个过程不会被清理。我怀疑终止这个进程会释放数据库文件。
尝试使用微软技术研究员Mark Russinovich编写的Process Explorer。这是Windows管理员/开发人员口袋里的标准瑞士军用工具。它可以向您显示哪些进程正在处理系统中的资源。
安装Process Explorer后,请尝试以下操作:
- 让你的系统进入故障状态(这样你的程序就无法运行了)
- 启动Process Explorer(您需要成为管理员才能充分利用其功能)
- 单击顶部菜单栏中的"查找",然后键入.mdf或.ldf文件的名称
搜索结果应该显示一个进程/服务,该进程/服务具有一个仍由错误终止的进程持有的资源的句柄。
使用SQL Server处理VS 2010和实体框架时,我已经多次遇到这种情况。在我的情况下,当我尝试运行程序时,在服务器资源管理器中打开了一个查询。一旦失败,我不得不放弃所有的连接,让它重新工作。
VS2010将在服务器资源管理器中使用的源数据库(.MDF
和.LDF
文件)复制到项目调试文件夹中。这是您在运行时使用的副本。当复制此文件时,默认情况下由MDF属性Copy to Output Directory
控制,并将其设置为Copy always
。这意味着它将尝试在新的构建或运行中复制文件,如果你在其他地方打开它,它会失败,然后挂断。
查看连接的方法是打开SQL Server管理控制台。默认情况下,VS2010使用连接字符串中指定的SQL Server用户实例。在实体框架的情况下,它在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
。
数据库将从列表中删除,您应该能够构建并运行应用程序。
我在以下位置找到了此解决方案:http://oreilly.com/catalog/errata.csp?isbn=0636920022220
右键单击VS的数据库资源管理器中的数据库,然后单击关闭调试会话之间的连接,这对我来说很有效。
最简单的方法是使用服务器资源管理器。选择问题数据库。右键单击并选择"关闭连接"。
如果它已经关闭,请连接并断开连接。
我认为已经附加了SqlTestDB.mdf。我以前遇到过这个问题,只需转到Ms Sql服务器并分离数据库,然后在Visual Studio中的服务器资源管理器中重建连接。
您在开始时打开数据库,但不确定它在完成时是否被释放。实际上,您正在等待内存管理器对其进行排序,这取决于系统的繁忙程度以及何时可以释放文件。
我认为您需要将此更改为"需要时打开"。
例如,我把访问任何数据库的代码放在它自己的类中,一旦操作完成,我就会释放它
打开和关闭确实有开销,但我发现我可以通过以下操作来接受它,
在类中有多个入口点,一个用于单个事务,另一个用于多个事务。例如
S_UpdateSingleRecord(...)
M_UpdateManyRecords(...)
我发现,在大多数应用程序中,这些应用程序可能是静态的,因为它们本身不存储数据,只在数据库之间传递数据。只有当我想为我的应用程序缓存一些东西时,它才会失去它的静态状态。
我在S_SingleTransaction()中使用"using",因为它会为我清理它。但我会打开Multiple入口点,并在调用函数完成时关闭它。我从来没有在一个mdf和一个应用程序中遇到过这种锁定问题。它将在一个mdf和多个应用程序中重新发挥作用,在这些情况下,您需要将MSSQL用作服务数据库,相反,您会发现在Visual Studio中设置它同样容易,然后在其他应用程序中,您的工具栏中的列表中已经有了该数据库。
转到Task Manager
(按Ctrl+Shift+Esc),转到选项卡Services
,按Name
排序并查找MSSSQLSERVER
。右键单击并选择Stop
,删除导致问题的文件(.mdf或.ldf)。右键再次单击MSSSQLSERVER
并选择"重新启动"。