Abbiamo un modulo piuttosto pesante su una delle nostre applicazioni interne che sta utilizzando SignalR per verificare la presenza di nuove notifiche. Siamo stati informati che stiamo creando blocchi sul database e che dovremmo prendere una lettura non vincolata per il metodo in questione.
Questo non è qualcosa che ho dovuto fare prima, e per quanto ne so EF di default prende una lettura di record impegnata. Quindi ho avvolto la query esistente in un'altra istruzione usando in questo modo:
public IEnumerable<ClientUpdates> GetNotifications(int forPaId)
{
using (var transactionScope =
new TransactionScope(TransactionScopeOption.Required, GetReadUncommitedTransactionOptions()))
{
using (var ctx = ContextFactory.CompanyDb)
{
// Do stuff
transactionScope.Complete();
return objectList;
}
}
}
private TransactionOptions GetReadUncommitedTransactionOptions()
{
var transactionOptions = new TransactionOptions
{
IsolationLevel = IsolationLevel.ReadUncommitted
};
return transactionOptions;
}
Questo risulta nel seguente messaggio di errore:
InvalidOperationException: avviso come eccezione di errore per l'avviso 'Microsoft.EntityFrameworkCore.Database.Transaction.AmbientTransactionWarning': è stata rilevata una transazione ambientale. Entity Framework Core non supporta le transazioni ambientali. Vedere http://go.microsoft.com/fwlink/?LinkId=800142 Per eliminare questa eccezione, utilizzare l'API DbContextOptionsBuilder.ConfigureWarnings. È possibile utilizzare ConfigureWarnings quando si esegue l'override del metodo DbContext.OnConfiguring o si utilizza AddDbContext sul provider del servizio dell'applicazione.
Quindi da quello ho cercato di sopprimere l'avvertimento:
services.AddDbContext<DbContext>(options =>
{
options.UseSqlServer(Configuration.GetConnectionString("MyConnectionString"));
options.ConfigureWarnings(x => x.Ignore(RelationalEventId.AmbientTransactionWarning));
});
Quale risulta in questo messaggio di errore:
NotSupportedException: l'integrazione nelle transazioni Ambient non è supportata.
Così ora sono un po 'perso, posso vedere gli altri hanno registrato questo problema sul tracker ufficiale dei problemi , ma non capisco quale sia il vero problema, e come posso forzare questo particolare modulo a fare una lettura "sporca" dei dati, in modo da fermare i blocchi che si verificano.
In primo luogo, il consiglio che stai ricevendo è un po 'antiquato. A partire da SQL Server 2005, le istantanee del database hanno attivato query senza blocco. Questo dovrebbe essere l'impostazione predefinita, ma suppongo sia possibile che potrebbe essere stato disattivato. Per ulteriori informazioni, consultare la documentazione pertinente . Lungo e breve, a condizione che sia abilitato, non è necessario preoccuparsi delle query che creano blocchi.
Secondo, c'è un bug in EF Core che attualmente impedisce il funzionamento del codice. Tuttavia, è già stato corretto, ma è ancora in fase di sviluppo (ovvero non è stato ancora implementato). Fondamentalmente, non puoi farlo adesso , ma presto sarai in grado di farlo. Se la prima soluzione non funziona, direi solo aspettare.
Infine, supponendo che la prima soluzione non funzioni per qualche motivo e non si può assolutamente aspettare che la soluzione venga implementata, è sempre possibile creare uno o più proc memorizzati per le query che utilizzano NOLOCK. Questo è ovviamente uno sforzo più manuale, quindi inizierei prima con le tue domande più pesanti. Esamina la query sia prima che dopo, e potresti anche prendere in considerazione l'idea di eseguire alcuni test di carico, solo per assicurarti che tu stia effettivamente acquistando qualcosa per lo sforzo.