База данных используется другим процессом ... но какой процесс? - PullRequest
5 голосов
/ 08 февраля 2012

Я написал очень маленькую программу на C #, которая использует очень маленькую базу данных SQL Server исключительно для обучения и тестирования.База данных используется в этом новом проекте и больше нигде.Тем не менее, у меня возникают проблемы при запуске отладки, когда программа не запускается, потому что база данных «используется другим процессом».

Если я перезагружаю свою машину, она будет работать снова, а затем через несколькопри выполнении тестов у меня снова возникнет та же проблема.

Я обнаружил много, много похожих проблем, о которых сообщалось по всему Интернету, но не могу найти однозначного ответа о том, как решить эту проблему.Во-первых, как мне узнать, что за «другой процесс» использует мои файлы .mdf & .ldf?Затем, как я могу получить эти файлы, чтобы они выпускались и не удерживались, чтобы не допустить повторения этого события раз за разом?ответы, которые вы мне даете !!!

Это мой код, как вы можете видеть, вы не могли получить ничего более базового, я, конечно, не должен сталкиваться с таким количеством проблем !!!

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 ]

6 голосов
/ 08 февраля 2012

Наиболее вероятные варианты:

  1. Предыдущий (сбойный) экземпляр вашей программы
  2. Visual Studio (с открытым дизайнером таблиц или чем-то подобным)

Вы можете проверить 1) с помощью TaskManager и 2), посмотрев в обозревателе серверов. Ваша БД должна показать маленький красный крестик, означающий «закрыто».

И вы должны переписать свой код, чтобы закрыть соединения как можно скорее. Используйте блоки try / finally или using(){ }.

1 голос
/ 10 февраля 2012

Это переписанный код с использованием операторов Using .Когда я запускаю программу и нажимаю «Вставить запись в файл SQL», все выключается, завершает процесс с myCount = 1 (хотя я не уверен на 100%, что он фактически выполняет физическую запись, я пропускаю команду, которая на самом деле«фиксирует» обновление?!?) и повторно отображает форму.

Если я снова нажимаю «Вставить запись в файл SQL», я получаю сообщение об ошибке:

SqlException был необработан

Невозможно открыть базу данных пользователя по умолчанию.Ошибка входа.Ошибка входа для пользователя 'MEDESKTOP \ Gary'.

Это программа (я единственный пользователь на этом ПК и обладаю полными правами администратора, "Состояние" базы данных на этом этапе:в соответствии с 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;
    }

}
}

Я не понимаю, почему я внезапно теряю доступ к своему собственному файлу, которым я являюсьуже используете?!?

0 голосов
/ 31 октября 2016

Вы открываете базу данных в начале и не уверены, что она будет освобождена после завершения.На самом деле вы ждете, когда менеджер памяти разберется с ним, это зависит от того, насколько система занята, когда файл может быть освобожден.

Я думаю, что вам нужно изменить это на «Открывать при необходимости».".

Я, например, поместил код для доступа к любой базе данных в своем собственном классе, после завершения действий я его освобождаю.

Открытие и закрытие действительно связано с издержками, но я обнаружил, чтоЯ могу жить с этим, выполнив следующее:

Имеют более одной точки входа в вашем классе, одну для отдельных транзакций и другую для нескольких транзакций.Например,

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

Я считаю, что в большинстве приложений они могут быть статическими, поскольку сами по себе они не хранят данные, а только передают их в базу данных и из нее.Он теряет свой статический статус, только если я хочу что-то кэшировать для своего приложения.

Я использую 'using' в S_SingleTransaction (), потому что это очищает его для меня.Но я оставляю множественную точку входа открытой и закрываю ее, когда моя вызывающая функция завершается.У меня никогда не было этой проблемы с блокировкой с одним mdf и одним приложением.Это вернулось бы к работе с одним mdf и несколькими приложениями, в этих случаях вам нужно вместо этого использовать MSSQL в качестве базы данных службы, вам будет проще установить ее в Visual Studio, а затем и в других приложениях, которые вы используете.эта база данных уже есть в списке на панели инструментов.

0 голосов
/ 21 февраля 2016

Я думаю, что уже есть SqlTestDB.mdf прилагается.Я сталкивался с этой проблемой раньше, просто зайдите на сервер MS Sql и отсоедините базу данных, а затем восстановите соединение в обозревателе серверов в Visual Studio.

0 голосов
/ 22 ноября 2012

Самое простое - это перейти в обозреватель серверов. Выберите проблемную базу данных. Щелкните правой кнопкой мыши и выберите «Закрыть соединение».

Если он уже закрыт, подключите и отключите.

0 голосов
/ 20 ноября 2012

Я нашел это решение по адресу: http://oreilly.com/catalog/errata.csp?isbn=0636920022220

Щелкните правой кнопкой мыши базу данных в проводнике баз данных VS и выберите тесное соединение между сеансами отладки, и это сработало для меня.

0 голосов
/ 02 августа 2012

Работа с VS 2010 и Entity Frameworks с использованием SQL Server Я сталкивался с этим более чем несколько раз.В моем случае это произошло, когда я попытался запустить программу, и у меня был открыт запрос в обозревателе сервера.После сбоя мне пришлось сбросить все соединения, чтобы он снова заработал.

VS2010 копирует исходную базу данных (файл .MDF и .LDF), с которым вы работаете в обозревателе сервера, в отладочную версию проектапапка.Это копия, с которой вы работаете во время выполнения.Когда этот файл копируется, он контролируется свойством MDF Copy to Output Directory, по умолчанию он имеет значение Copy always.Это означает, что он попытается скопировать файл при новой сборке или запуске, и если он будет открыт в другом месте, произойдет сбой, а затем он зависнет.

Чтобы увидеть соединение, нужно открыть Управление SQL Server.Приставка.По умолчанию VS2010 использует пользовательский экземпляр SQL Server, как указано в строке подключения.В случае Entity Frameworks он находится в XML-файле App.Config.

Экземпляр пользователя - это отдельная в памяти копия SQL Server, которая имеет все права пользователя, назначенные вошедшему в систему пользователю.Чтобы добраться до него, вам нужно найти правильное соединение.

Выполнение этого запроса из основного экземпляра SQL покажет все соединения User Instance.

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.

*.1027 * База данных будет удалена из списка, и вы сможете создать и запустить приложение.
0 голосов
/ 08 февраля 2012

Попробуйте использовать Process Explorer , написанный Марком Руссиновичем, техническим сотрудником Microsoft. Это стандартный инструмент швейцарской армии в кармане администраторов и разработчиков Windows. Он может показать вам, какие процессы удерживают дескрипторы ресурсов в системе.

После того, как вы установили Process Explorer, попробуйте следующее:

  1. Переведите вашу систему в состояние сбоя (такое, что ваша программа не работает).
  2. Запустите Process Explorer (вам необходимо быть администратором, чтобы в полной мере использовать его функции).
  3. Нажмите «Найти» в строке меню вверху и введите имя вашего файла .mdf или .ldf.

Результаты поиска должны отображать процесс / службу с дескриптором одного из ресурсов, все еще удерживаемых неправильно завершенным процессом.

0 голосов
/ 08 февраля 2012

IIRC с использованием AttachDbFilename запускает процесс SqlServr.exe, работающий под учетной записью пользователя, которую использует ваш процесс, отдельно от экземпляра SqlServer, выполняющегося как служба (поэтому остановка службы MsSqlServer не решит эту проблему). В случае грязного выхода, иногда этот процесс не очищается. Я подозреваю, что уничтожение этого процесса освободит файлы БД.

0 голосов
/ 08 февраля 2012

попробуйте запустить sp_who2, чтобы увидеть список процессов.

К вашему сведению: вам не нужно перезагружать компьютер, в худшем случае перезапустите службу SQL Server

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...