Самый простой способ - использовать некоторый слушатель, где вы можете выдать исключение и подписать этого слушателя на dbContext
.
public class CommandListener
{
[DiagnosticName("Microsoft.EntityFrameworkCore.Database.Command.CommandExecuting")]
public void OnCommandExecuting(DbCommand command, DbCommandMethod executeMethod, Guid commandId, Guid connectionId, bool async, DateTimeOffset startTime)
{
throw new TimeoutException("Test exception");
}
[DiagnosticName("Microsoft.EntityFrameworkCore.Database.Command.CommandExecuted")]
public void OnCommandExecuted(object result, bool async)
{
}
[DiagnosticName("Microsoft.EntityFrameworkCore.Database.Command.CommandError")]
public void OnCommandError(Exception exception, bool async)
{
}
}
Подписаться слушателя на dbContext
fi в Startup.cs
var context = provider.GetService<SomeDbContext>();
var listener = context.GetService<DiagnosticSource>();
(listener as DiagnosticListener).SubscribeWithAdapter(new CommandListener());
Поскольку TimeoutException
является временным исключением в SqlServerRetryingExecutionStrategy.cs
(если вы используете стратегию повторения по умолчанию), выполучит TimeoutException
столько, сколько имеет ваша MaxRetryingCount
настройки стратегии.Наконец, вы должны получить RetryLimitExceededException
в результате запроса.
Вы должны увидеть TimeoutException
в журналах своего приложения.Также неплохо включить журналы транзакций "Microsoft.EntityFrameworkCore.Database.Transaction": "Debug"
То, что я сделал, чтобы выработать стратегию переходных исключений и отладки (только для тестирования и игры с целью)
- Iдобавлено
ExectuionStrategyBase.cs
и TestServerRetryingExecutionStrategy.cs
.Первый - это клон ExectuionStrategy.cs
, а второй - клон SqlServerRetryingExecutionStrategy.cs
В Startup.cs я установил стратегию повторных попыток
strategy services.AddDbContext<SomeDbContext>(options =>
{options.UseSqlServer(Configuration.GetConnectionString("DefaultConnection"), sqlOption =>
{
sqlOption.ExecutionStrategy(dependencies =>
{
return new TestSqlRetryingStrategy(
dependencies,
settings.SqlMaxRetryCount,
settings.SqlMaxRetryDelay,
null);
});<br>
});
В OnCommandExecuting
из CommandListener.sc
я только что проверил некоторую статическую переменную bool
, бросать или нет TimeoutException
, и в ExectuionStrategyBase.cs
я перевернул эту переменную.
Таким образом, мне удалось сгенерировать переходный процесс Exception
при первом выполнении запроса и успешное выполнение при втором коротком замыкании.Теперь я думаю о какой-то долго выполняющейся транзакции и завершаю сеанс этой транзакции в SSCM во время ее выполнения.
Кроме того, я обнаружил, что при наличии запроса типа var users = context.Users.AsNoTracking().ToArrayAsync()
стратегия выполнения не реализуется, и язастрял на нем.Я боролся с этим пару дней, но до сих пор ничего не могу понять.Если удалить AsNoTracking
или заменить ToArrayAsync()
чем-то вроде FirstAsync()
, то все противники хорошо.