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

时间:2012-02-08 14:41:14

标签: c# sql-server visual-studio-2010

我编写了一个非常小的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();
        }
    }
}

10 个答案:

答案 0 :(得分:6)

最有可能的选择:

  1. 您程序的先前(崩溃)实例
  2. Visual Studio(表设计器打开或类似)
  3. 您可以通过查看Server Explorer来检查1)与TaskManager和2)。你的数据库应该显示一个小红叉,意思是'关闭'。

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

答案 1 :(得分:1)

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

如果我再次点击Insert Record Into SQL File,我会收到如下错误:

  

SqlException未处理

     

无法打开用户默认数据库。登录失败。用户登录失败   'MEDESKTOP \加里'。

这是程序(我是这台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;
    }

}
}

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

答案 2 :(得分:0)

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

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

答案 3 :(得分:0)

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

答案 4 :(得分:0)

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

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

  1. 让您的系统进入失败状态(这样运行程序不起作用)。
  2. 启动Process Explorer(您需要成为管理员才能充分利用其功能)。
  3. 点击顶部菜单栏中的“查找”,然后输入.mdf或.ldf文件的名称。
  4. 搜索结果应显示一个流程/服务,其中一个资源仍由错误终止的流程保留。

答案 5 :(得分:0)

使用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复选框,然后点击{ {1}}。

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

答案 6 :(得分:0)

我在http://oreilly.com/catalog/errata.csp?isbn=0636920022220

找到了这个解决方案

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

答案 7 :(得分:0)

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

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

答案 8 :(得分:0)

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

答案 9 :(得分:0)

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

我认为您需要将此更改为&#34;在需要时打开&#34;。

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

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

您的班级中有多个入口点,一个用于单个交易,另一个用于多个交易。例如

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

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

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