Servizio Windows con Entity Framework Core rallenta tantissimo SqlServer

di il
11 risposte

Servizio Windows con Entity Framework Core rallenta tantissimo SqlServer

Gentili,
sto avendo delle difficoltà con un servizio creato con .Net Core 3.1 che resta in ascolto e periodicamente (con timer minimo di 5 minuti) deve effettuare delle operazioni su SqlServer e più precisamente importare delle righe da due tabelle che vengono alimentate da un ecommerce ad altre due tabelle che servono al gestionale aziendale.
Utilizzo Entity Framework Core 3.1, e tutte le chiamate e le query che devono valutare delle pre-condizioni sono asincrone, il context viene creato mediante using per chiudere le connessioni al termine del "lavoro".
Il cliente mi dice che durante l'esecuzione del servizio, l'accesso tramite il gestionale a SqlServer diventa lentissimo.
Ho provato a riverificare più volte tutte le operazioni lanciate sul server tramite EF, ed ho usato sempre la versione asincrona con relativo await, tutti i metodi sono definiti con async Task, e per il momento le righe da gestire non sono tantissime, max qualche centinaio.
L'unica cosa che, mi sono accorto, non ho implementato nella stringa di connessione è il MultipleActiveResultSets, secondo voi può dipendere da questo?
Altri suggerimenti per verificare?
Ringrazio chiunque voglia darmi qualche dritta.
Lucius.

11 Risposte

  • Re: Servizio Windows con Entity Framework Core rallenta tantissimo SqlServer

    luciusinfabula ha scritto:


    Il cliente mi dice che durante l'esecuzione del servizio, l'accesso tramite il gestionale a SqlServer diventa lentissimo.
    Difficile fare supposizioni senza avere almeno un esempio di codice da guardare o avere una idea della struttura delle tabelle su cui vai ad agire sia dal servizio sia dal gestionale.
  • Re: Servizio Windows con Entity Framework Core rallenta tantissimo SqlServer

    Salve Marco,
    si mi rendo conto, speravo ci fosse magari qualche tool di cui io ignoravo l'esistenza che potesse monitorare il carico di SqlServer.
    ====
    Edit:
    Spulciando tra i tool di SqlServer ho notato il: Monitoraggio Attività.
    Sto facendo delle prove sul suo utilizzo.
  • Re: Servizio Windows con Entity Framework Core rallenta tantissimo SqlServer

    Salve,
    come primo acchito, puoi provare ad utilizzare da https://www.brentozar.com/first-aid, le procedure sp_BlitzFirst, sp_BlitzWho e magari sp_WhoIsActive http://whoisactive.com, giusto per vedere come stanno un po' le cose...
    salutoni romagnoli
    --
    Andrea
  • Re: Servizio Windows con Entity Framework Core rallenta tantissimo SqlServer

    Salve Andrea,
    scusa il ritardo della risposta, da quello che mi riferisce il cliente non mi sembra che abbia ancora problemi, potrebbe essere stata una semplice coincidenza, comunque proverò sicuramente i tuoi suggerimenti, anche nell'eventualità di possibili problemi futuri.
    Ti ringrazio, scusandomi ancora per il ritardo della risposta.
    Salutoni veneti.
    Lucius
  • Re: Servizio Windows con Entity Framework Core rallenta tantissimo SqlServer

    Gentili,
    ritorno su questo problema che mi sta creando forti mal di testa, il cliente giustamente vuole una risposta.
    Da quello che ho capito è Entity Framework (.Net Core 3.1) che blocca l'accesso alle tabelle su cui sta scrivendo dopo aver aperto la transaction, se infatti evito di usarla non mi blocca l'accesso.
    Io faccio così:
    
    	// Per ogni ordine nella tabella OrdiniClientiDaCrm
    	await using EfContext dbCtx = new EfContext(configurazione.ConnessioneDatabase);	// Efcontext è il dbContext EF
    	await using var transaction = await dbCtx.Database.BeginTransactionAsync();
    
    	//inserisco l'ordine nella tabella ordini_clienti con una stored_procedure
    	.......
    		
    	//per ogni riga di acquisto relativo all'ordine leggo nella tabella OrdiniClientiDaCrmSotto
    	//inserisco le righe nella tabella ordini_clienti_sotto con una stored_procedure
    	.......
    		
    	// se tutto va bene
    	await dbCtx.SaveChangesAsync();
    	await transaction.CommitAsync();
    
    So che non è il metodo più veloce ed efficiente creare per ogni ordine il context e la transaction ma volevo essere il più conservativo possibile perché si tratta di un servizio e l'inserimento degli ordini e delle relative righe viene fatto tramite stored procedure, e non mi sembra che EF tenga il tracking delle stesse come nell'inserimento usando le relative entità.
    La mia paura è che venga inserito solo l'ordine magari senza le righe o solo con parte delle righe.

    Sono preso un po' male, accetto consigli.
    Grazie in anticipo a chi mi risponderà.
    Lucius
  • Re: Servizio Windows con Entity Framework Core rallenta tantissimo SqlServer

    Sei obbligato ad usare entity framework?
  • Re: Servizio Windows con Entity Framework Core rallenta tantissimo SqlServer

    Salve,
    di solito per l'accesso ai dati utilizziamo Entity Framework oppure Dapper, è che ormai ho fatto tutto in Entity Framework.
    Oltre all'inserimento, devo anche fare periodicamente l'aggiornamento al contrario cioè da ordini/righeordini principale alle tabelle relative del CRM ma per quelle non essendoci stored procedure ho tirato via le transactions e faccio un solo SaveChangeAsync alla fine, se va in tilt il metodo lo riprendo più tardi.
    Il problema con quel cliente è che non ci fornisce dati reali e devo sempre crearne qualcuno di fittizio, solo che loro hanno molti record.
    Lucius
  • Re: Servizio Windows con Entity Framework Core rallenta tantissimo SqlServer

    luciusinfabula ha scritto:


    l'inserimento degli ordini e delle relative righe viene fatto tramite stored procedure, e non mi sembra che EF tenga il tracking delle stesse come nell'inserimento usando le relative entità.
    A questo punto, qual è lo scopo di usare EF se l'inserimento avviene tramite stored procedure?
    Inoltre, se non ricordo male, puoi gestire una transazione anche all'interno della stored, e magari potresti crearne una che accetti tutti i parametri della testata e anche i dettagli, usando un "Table Type".

    Mi risulta molto strano che un inserimento blocchi di fatto una tabella intera, e considerando quant'è la durata dell'operazione, che questo persista con un tempo capace di influire su altre operazioni o addirittura creare colli di bottiglia nell'applicazione.
  • Re: Servizio Windows con Entity Framework Core rallenta tantissimo SqlServer

    Salve Marco,
    grazie a tutti intanto per le risposte.
    Di solito usiamo EF per tutte le iterazioni con i db, è il modo prediletto in azienda, o EF o Dapper per le cose "svolazzanti".
    La mia è essenzialmente poca esperienza con EF, ormai capisco abb. bene il funzionamento di base e la logica ma devo entrare ancora in profondità nell'uso.
    Riguardando tutto il codice per l'ennesima volta ho visto SICURAMENTE UN ERRORE DI CONCETTO: in pratica spedivo le mail al verificarsi di "errori" nelle tabelle da importare, prima di chiudere la transazione e ricominciare con le righe successive; adesso la spedizione è stata spostata fuori dal ciclo di inserimento, alla fine.
    Ho riprovato ed effettivamente all'avvio del servizio inizialmente dà meno problemi, perché chiaramente non dovendo attendere la spedizione delle mail la transazione è più veloce, ma comunque dopo un certo punto inizia a causare dei blocchi agli utenti normali, che usano il gestionale.
    E' proprio l'importazione in catena che secondo me provoca ad un certo punto il collo di bottiglia, forse perché le stored procedure (quella per l'intestazione e le righe) devono fare anche delle select interne per inserire i dati mancanti che magari creano dei lag.
    Adesso riguardo di nuovo il codice, sono d'accordo comunque con il cliente che il servizio, siccome rifa la procedura ogni tot minuti, di default 10, mi importa un numero max di ordini, venti, più che sufficienti per il flusso; solo all'inizio del lancio essendoci qualche centinaia di ordini ritarderà al massimo una o due orette.

    PS: mi sono dimenticato di riportare che avendo fatto il logging degli errori tramite try...catch effettivamente ritorna errori di timeout nell'esecuzione.
    Grazie ancora.
    Lucius
  • Re: Servizio Windows con Entity Framework Core rallenta tantissimo SqlServer

    Gentili,
    ritorno sul problema l'ultima volta.
    Il problema essenzialmente è causato da una mia superficialità, non avendo loggato tutte le fasi dell'importazione per capire dove stava il collo di bottiglia.
    In realtà il problema non è dovuto ad Entity Framework/transactions oppure a metodi errati async ma all'effettiva lunghezza della stored procedure in Sql Server che inserisce la riga nel db fisico.
    Dopo aver loggato tutto il possibile inizio-fine di ogni "chiamata" EF, stored procedure ho fatto lo stesso nella stored procedure e provata direttamente in Sql-Server del cliente.
    C'è in particolare una procedura all'interno che da sola bloccava tutto, facendo l'aggiornamento dei prezzi standard di tutte le righe della tabella articoli che nel db del cliente è immensa.
    Morale: colpa mia che non avevo loggato tutte le fasi del servizio, spaccherei tutto.
    Saluti a tutti.
    Lucius
  • Re: Servizio Windows con Entity Framework Core rallenta tantissimo SqlServer

    luciusinfabula ha scritto:


    In realtà il problema non è dovuto ad Entity Framework/transactions oppure a metodi errati async ma all'effettiva lunghezza della stored procedure in Sql Server che inserisce la riga nel db fisico.
    [...]
    Morale: colpa mia che non avevo loggato tutte le fasi del servizio, spaccherei tutto.
    Come si dice in questi casi, tutto è bene quel che finisce... (bene o male che sia).
    Grazie per l'aggiornamento.
Devi accedere o registrarti per scrivere nel forum
11 risposte