Я испытываю ошибки подключения к базе данных с приложением ASP. NET, написанным на VB, работающем на трех серверах IIS. Основной базой данных является MS Access, который находится на общем сетевом устройстве. Он использует Entity Framework, первую реализацию кода и JetEntityFrameworkProvider.
Приложение работает стабильно. Но примерно 1 из 1000 попыток открыть соединение с базой данных завершается неудачно с одной из следующих двух ошибок:
06:33:50 DbContext "Failed to open connection at 2/12/2020 6:33:50 AM +00:00 with error:
Cannot open database ''. It may not be a database that your application recognizes, or the file may be corrupt.
или
14:04:39 DbContext "Failed to open connection at 2/13/2020 2:04:39 PM +00:00 with error:
Could not use ''; file already in use.
Через одну секунду с обновлением (F5 ), ошибка исчезла и снова работает.
Подробная информация о среде и используемом коде.
Строка подключения
<add name="DbContext" connectionString="Provider=Microsoft.Jet.OLEDB.4.0;Data Source=x:\thedatabase.mdb;Jet OLEDB:Database Password=xx;OLE DB Services=-4;" providerName="JetEntityFrameworkProvider" />
Управление DbContext
Приложение использует свойство publi c для доступа к DbContext. DbContext хранится в коллекции HttpContext.Current.Items в течение всего срока действия запроса и располагается в его конце.
Public Shared ReadOnly Property Instance() As DbContext
Get
SyncLock obj
If Not HttpContext.Current.Items.Contains("DbContext") Then
HttpContext.Current.Items.Item("DbContext") = New DbContext()
End If
Return HttpContext.Current.Items.Item("DbContext")
End SyncLock
End Get
End Property
BasePage в единицах и располагает DbContext.
Protected Overrides Sub OnInit(e As EventArgs)
MyBase.OnInit(e)
DbContext = Data.DbContext.Instance
...
End Sub
Protected Overrides Sub OnUnload(e As EventArgs)
MyBase.OnUnload(e)
If DbContext IsNot Nothing Then DbContext.Dispose()
End Sub
То, что я пробовал
Многие из вопросов по SO, которые касаются вышеупомянутых сообщений об ошибках, обычно касаются невозможности установить sh соединение к базе данных - они не могут подключиться вообще. В этом случае все по-другому. Соединение работает в 99,99% случаев.
Кроме того, я проверил:
- Разрешения: Полный доступ предоставляется для общего ресурса, где .mdb (база данных) и .ldb ( файл блокировки).
- Сетевое подключение: нет проблем с подключением к общему устройству; это соединение Gigabit LAN
- Максимальное число одновременных подключений не достигло 255
- Максимальный размер базы данных не превышен (дБ имеет только 5 МБ)
- Изменен параметр компиляции с «Любой процессор» - «x86», как предложено в этом MS Dev- Net post
Цитата: Я получаю то же самое «Не могу открыть базу данных» ошибка, но совершенно случайно (казалось). Файл MDB был меньше 1 МБ, поэтому с этой ошибкой не было проблем с лимитом в 2 ГБ, как уже упоминалось. Он работал на 100% на 32-битных версиях windows, но я обнаружил, что проблемы были на 64-битных установках. Приложение компилировалось как «Любой процессор». Я изменил параметр компиляции с «Любой процессор» на «x86», и проблема исчезла.
Пока ничего не помогло.
Чтобы собрать больше информации, я прикрепил регистратор Nlog к DbContext, который записывает все действия базы данных и запросы в файл журнала.
Shared Log As Logger = LogManager.GetLogger("DbContext")
Me.Database.Log = Sub(s) Log.Debug(s)
Исследуя журналы, я выяснил, что когда один из вышеуказанные ошибки произошли на одном сервере, другой сервер (всего 3) закрыл соединение с БД в одно и то же время. Вот два примера, которые соответствуют вышеуказанным ошибкам:
06:33:50 DbContext "Closed connection at 2/12/2020 6:33:50 AM +00:00
14:04:39 DbContext "Closed connection at 2/13/2020 2:04:39 PM +00:00
Предположение
Когда все соединения DbContext были закрыты, соответствующая запись удаляется из. LDB файл блокировки. При открытии соединения с БД запись будет добавлена в файл блокировки. Когда эти два события происходят в одно и то же время на двух разных серверах, возникает конфликт записи в файл блокировки .ldb, что приводит к появлению указанных выше ошибок.
Вопрос
Может кто-нибудь подтвердить или доказать, что это неправильно? Кто-нибудь испытывал такое поведение? Может быть, я что-то упускаю. Буду признателен за ваш вклад и опыт в этом вопросе.
Если мое предположение верно, решение может заключаться в использовании вспомогательного класса для доступа к БД, который перехватывает и обрабатывает эту ошибку, ожидая минимального периода времени и пытаясь снова.
Но это кажется неправильным. Поэтому я также открыт для предложений по «правильному» решению.
РЕДАКТИРОВАТЬ:"Правильное" решение будет использовать сервер СУБД (как указано в комментариях ниже). Я знаю об этом. На данный момент, я должен иметь дело с этой ошибкой проекта, не будучи ответственным за это. Кроме того, я не могу изменить это в краткосрочной перспективе.