Reasoning
Я нахожусь в несколько уродливой ситуации.
Мне нужен DbTransaction
, обернутый вокруг «API плагина», к которому потенциальные клиенты и другие люди имеют доступ , что позволяет мне откатить изменения, внесенные в базу данных, если что-то пойдет не так (иначе: случаются исключения).
Раньше я предоставлял один DbContext
для этого, но это оказалось сложной задачей для более сложного кода, заполняя изменить трекер на быстрое (что: падение производительности, интенсивное использование памяти и т. д. c.)
Я перешел на новый дизайн, позволяющий запускать несколько DbContexts, но теперь возникла проблема: Entity Framework 6 с НПГ SQL жалуется, вызывается момент DbContext.SaveChanges()
.
A transaction is already in progress; nested/concurrent transactions aren't supported.
at Npgsql.NpgsqlConnection.BeginTransaction(IsolationLevel level)
at System.Data.Entity.Infrastructure.Interception.InternalDispatcher`1.Dispatch[TTarget,TInterceptionContext,TResult](TTarget target, Func`3 operation, TInterceptionContext interceptionContext, Action`3 executing, Action`3 executed)
at System.Data.Entity.Infrastructure.Interception.DbConnectionDispatcher.BeginTransaction(DbConnection connection, BeginTransactionInterceptionContext interceptionContext)
at System.Data.Entity.Core.EntityClient.EntityConnection.BeginDbTransaction(IsolationLevel isolationLevel)
Упрощенный пример кода
// Example. Resides in another assembly
async Task Plugin(DbConnection dbConnection)
{
using (var cntxt = new Database.Context(dbConnection))
{
cntxt.LogMessages.Add("Fancy Log Message");
await cntxtb.SaveChangesAsync();
}
}
// Simplified version of what actually happens
void PluginCaller()
{
using var dbConnection = Database.Context.Connection(usereadonly: false);
using var dbTransaction = dbConnection.BeginTransaction();
Plugin(dbConnection).Wait();
}
Теперь возникает вопрос:
Как я могу принудить к выполнению большой транзакции независимо от того, что делают плагины, чтобы предотвратить повреждение базы данных неисправным плагином (в этом смысле повреждение означает: в следующий раз плагин работает, все в порядке, но некоторые элементы могут быть созданы дважды из плагина, вызывая больше ошибок)
Примечание:
Я уже пытался использовать TransactionScope
для этого, но это дало то же исключение.