Implement workaround for "To many tables" error:

ODBC Error Code: -1311 [HY001]
[Microsoft][ODBC Microsoft Access Driver] Cannot open any more tables.
If too many commands get executed in short succession, ACE/Jet can run out of table handles.
This can happen despite proper disposal of OdbcCommand and OdbcDataReader objects.
Waiting for a couple of milliseconds will give ACE/Jet enough time to catch up.
pull/46/head
Lau 6 years ago
parent d502f6e3c6
commit 11d56f868c

@ -1,6 +1,7 @@
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System;
using System.Data.Jet;
using System.Data.OleDb;
using JetBrains.Annotations;
@ -13,108 +14,30 @@ namespace EntityFrameworkCore.Jet.Storage.Internal
{
public static bool ShouldRetryOn([NotNull] Exception ex)
{
var sqlException = ex as OleDbException;
if (sqlException != null)
DataAccessType dataAccessType;
var exceptionFullName = ex.GetType().FullName;
if (exceptionFullName == "System.Data.OleDb.OleDbException")
dataAccessType = DataAccessType.OleDb;
else if (exceptionFullName == "System.Data.Odbc.OdbcException")
dataAccessType = DataAccessType.Odbc;
else
return false;
dynamic sqlException = ex;
foreach (var err in sqlException.Errors)
{
foreach (OleDbError err in sqlException.Errors)
// TODO: Check additional ACE/Jet Errors
switch (err.NativeError)
{
// TODO: Check proper Jet Errors
/*
switch (err.NativeError)
{
// SQL Error Code: 49920
// Cannot process request. Too many operations in progress for subscription "%ld".
// The service is busy processing multiple requests for this subscription.
// Requests are currently blocked for resource optimization. Query sys.dm_operation_status for operation status.
// Wait until pending requests are complete or delete one of your pending requests and retry your request later.
case 49920:
// SQL Error Code: 49919
// Cannot process create or update request. Too many create or update operations in progress for subscription "%ld".
// The service is busy processing multiple create or update requests for your subscription or server.
// Requests are currently blocked for resource optimization. Query sys.dm_operation_status for pending operations.
// Wait till pending create or update requests are complete or delete one of your pending requests and
// retry your request later.
case 49919:
// SQL Error Code: 49918
// Cannot process request. Not enough resources to process request.
// The service is currently busy.Please retry the request later.
case 49918:
// SQL Error Code: 41839
// Transaction exceeded the maximum number of commit dependencies.
case 41839:
// SQL Error Code: 41325
// The current transaction failed to commit due to a serializable validation failure.
case 41325:
// SQL Error Code: 41305
// The current transaction failed to commit due to a repeatable read validation failure.
case 41305:
// SQL Error Code: 41302
// The current transaction attempted to update a record that has been updated since the transaction started.
case 41302:
// SQL Error Code: 41301
// Dependency failure: a dependency was taken on another transaction that later failed to commit.
case 41301:
// SQL Error Code: 40613
// Database XXXX on server YYYY is not currently available. Please retry the connection later.
// If the problem persists, contact customer support, and provide them the session tracing ID of ZZZZZ.
case 40613:
// SQL Error Code: 40501
// The service is currently busy. Retry the request after 10 seconds. Code: (reason code to be decoded).
case 40501:
// SQL Error Code: 40197
// The service has encountered an error processing your request. Please try again.
case 40197:
// SQL Error Code: 10929
// Resource ID: %d. The %s minimum guarantee is %d, maximum limit is %d and the current usage for the database is %d.
// However, the server is currently too busy to support requests greater than %d for this database.
// For more information, see http://go.microsoft.com/fwlink/?LinkId=267637. Otherwise, please try again.
case 10929:
// SQL Error Code: 10928
// Resource ID: %d. The %s limit for the database is %d and has been reached. For more information,
// see http://go.microsoft.com/fwlink/?LinkId=267637.
case 10928:
// SQL Error Code: 10060
// A network-related or instance-specific error occurred while establishing a connection to Jet.
// The server was not found or was not accessible. Verify that the instance name is correct and that Jet
// is configured to allow remote connections. (provider: TCP Provider, error: 0 - A connection attempt failed
// because the connected party did not properly respond after a period of time, or established connection failed
// because connected host has failed to respond.)"}
case 10060:
// SQL Error Code: 10054
// A transport-level error has occurred when sending the request to the server.
// (provider: TCP Provider, error: 0 - An existing connection was forcibly closed by the remote host.)
case 10054:
// SQL Error Code: 10053
// A transport-level error has occurred when receiving results from the server.
// An established connection was aborted by the software in your host machine.
case 10053:
// SQL Error Code: 1205
// Deadlock
case 1205:
// SQL Error Code: 233
// The client was unable to establish a connection because of an error during connection initialization process before login.
// Possible causes include the following: the client tried to connect to an unsupported version of Jet;
// the server was too busy to accept new connections; or there was a resource limitation (insufficient memory or maximum
// allowed connections) on the server. (provider: TCP Provider, error: 0 - An existing connection was forcibly closed by
// the remote host.)
case 233:
// SQL Error Code: 121
// The semaphore timeout period has expired
case 121:
// SQL Error Code: 64
// A connection was successfully established with the server, but then an error occurred during the login process.
// (provider: TCP Provider, error: 0 - The specified network name is no longer available.)
case 64:
// DBNETLIB Error Code: 20
// The instance of Jet you attempted to connect to does not support encryption.
case 20:
return true;
// This exception can be thrown even if the operation completed succesfully, so it's safer to let the application fail.
// DBNETLIB Error Code: -2
// Timeout expired. The timeout period elapsed prior to completion of the operation or the server is not responding. The statement has been terminated.
//case -2:
}
*/
// ODBC Error Code: -1311 [HY001]
// [Microsoft][ODBC Microsoft Access Driver] Cannot open any more tables.
// If too many commands get executed in short succession, ACE/Jet can run out of table handles.
// This can happen despite proper disposal of OdbcCommand and OdbcDataReader objects.
// Waiting for a couple of milliseconds will give ACE/Jet enough time to catch up.
case -1311 when dataAccessType == DataAccessType.Odbc:
return true;
}
return false;
@ -128,4 +51,4 @@ namespace EntityFrameworkCore.Jet.Storage.Internal
return false;
}
}
}
}

@ -2,6 +2,7 @@
using System.IO;
using System.Linq;
using System.Text.RegularExpressions;
using System.Threading;
using Microsoft.VisualStudio.TestTools.UnitTesting;
namespace System.Data.Jet.Test
@ -42,21 +43,35 @@ namespace System.Data.Jet.Test
using var command = _connection.CreateCommand();
var script = File.ReadAllText(_scriptPath);
foreach (var batch in
new Regex(@"^GO", RegexOptions.IgnoreCase | RegexOptions.Multiline, TimeSpan.FromMilliseconds(1000.0))
.Split(script)
.Where(b => !string.IsNullOrEmpty(b)))
var batches = new Regex(@"\s*;\s*", RegexOptions.IgnoreCase | RegexOptions.Multiline, TimeSpan.FromMilliseconds(1000.0))
.Split(script)
.Where(b => !string.IsNullOrEmpty(b))
.ToList();
var retryWaitTime = TimeSpan.FromMilliseconds(250);
const int maxRetryCount = 6;
var retryCount = 0;
foreach (var batch in batches)
{
command.CommandText = batch;
try
{
command.ExecuteNonQuery();
retryCount = 0;
}
catch (Exception e)
{
Console.WriteLine(e.Message);
Console.WriteLine(batch);
throw;
if (retryCount >= maxRetryCount)
{
Console.WriteLine(e.Message);
Console.WriteLine(batch);
throw;
}
retryCount++;
Thread.Sleep(retryWaitTime);
}
}
}

Loading…
Cancel
Save