Настольное приложение C # выдает ошибку при доступе к базе данных Access (mdb) - PullRequest
0 голосов
/ 22 февраля 2012

Я пишу настольное приложение на C #.Он использует базу данных MS Access MDB.Время от времени я получаю странные ошибки, подобные приведенной ниже.У меня есть несколько потоков, обращающихся к базе данных, но все они блокируют доступ (с ключевым словом lock()).

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

Этот обнаружился, когда приложение попыталось прочитать некоторые данные из базы данных:

System.InvalidOperationException: Internal .Net FrameworkОшибка поставщика данных 12. в System.Data.ProviderBase.DbConnectionInternal.CreateReferenceCollection () в System.Data.ProviderBase.DbConnectionInternal.AddWeakReference (значение объекта, тег Int32) в System.Data.OleDb.OleDbConnection.AddWeakReference (значение объекта Int32,) в System.Data.OleDb.OleDbCommand.ExecuteReaderInternal (поведение CommandBehavior, метод String) в System.Data.OleDb.OleDbCommand.ExecuteReader (поведение CommandBehavior) в System.Data.OleDb.OleDbCommand.Executeager.Reader ()(Int32 lastRetrievedUpdateId) в c: \ Users \ myaccount \ WORKSPACE \ SharpDevelop_Projects \ myapp \ Classes_Data \ DBManager.cs: строка 567

Ответы [ 2 ]

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

Кажется, я решил проблему.У меня есть два отдельных файла MDB для моего приложения и два отдельных фоновых потока - каждый из них имеет доступ к своему собственному файлу MDB соответственно (один поток использует один файл, другой - другой файл).Вначале я ошибочно предположил, что если эти потоки работают отдельно и имеют доступ к отдельным файлам, проблем не будет.

К сожалению, оказывается, что в вашем приложении может быть только одно соединение с любым файлом базы данных на любом моменте..

Теперь я блокирую доступ ко всем файлам, используя только одну блокировку для всех потоков (поэтому только один поток может получить доступ к любому файлу), и я больше не получаю сообщение об ошибке!

СпецифичноПример кода для тех, кто столкнулся с той же проблемой:

Object dbLock = new Object(); //make it a field in the database managing singleton class

В методе, используемом любым потоком, используйте:

lock(dbLock) //lock out db access from other threads (reserve for this thread only)
{
   //here goes some code which will run only when the thread manages to lock the dbLock
   //this code should accesses your database by creating and opening
   //a new connection and then closing it in the same block
}

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

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

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

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

Многопоточный доступ к базе данных из одного и того же приложения может стать проблематичным, особенно с Access.

По этой причине большинство людей получают доступ к базе данных через одноэлементный класс.

Возможно, вы столкнулись с исключением из-за конфликтов блокировки при извлечении данных из базы данных.

...