6 messaggi dal 17 settembre 2015
Ciao a tutti,questa è la mia ultima spiaggia.... Allora, sto sviluppando una applicazione web che prevede di importare da un file excel circa 80k righe. Prima di riversare il contenuto sul database faccio delle operazioni di check riga per riga per vedere se il cliente non è già presente nel database mediante il codice fiscale ed un numero domanda se positivo lo salto e fin qui nessun problema solo un pò lento ma è normale. Il problema nasce quando metto questa applicazione su vari server di produzione con iis 8 (win2012 server). Infatti quando lancio l'upload del file , il file viene uploadato correttamente ma quando effettua l'import vero e proprio dopo circa 40 secondi mi da il messaggio che il file è stato importato ma se guardo nella tabella dell'sql (vers. 16) vedo che mi ha caricato solo 3368 clienti a fronte di 17300 senza darmi errore e niente altro. Se provo a fare la stessa cosa sulla mia macchina lanciando l'applicazione da Visual Studio 2015 e facndo l'upload il file viene importato correttamente con tutti i 17300 clienti. Ho pensato a qualcosa come un timeout o altro ... ho provato di tutto ma niente-
Mi potreste dare una mano ?

Grazie anticipatamente.
Giuseppe

Al presente inserisco il codice con il quale faccio questa operazione:

****** SUB CHIAMANTE *****

Protected Sub btnInserisci_Click(sender As Object, e As EventArgs) Handles btnInserisci.Click
If FileUpload1.HasFile Then
FileUpload1.BackColor = Drawing.Color.White

UploadThisFile(FileUpload1)
Else
FileUpload1.BackColor = Drawing.Color.Red
lblError.Text = "Inserimento file obbligatorio"
End If
End Sub


Protected Sub UploadThisFile(ByVal upload As FileUpload)
Dim con As New SqlConnection(ConfigurationManager.ConnectionStrings("nomeconnessione").ConnectionString)
Dim format As String = "dd/MM/yyyy"
Dim ident As String
Dim DataInserimento As Date = txtDataIns.Text
Dim connString As String = WebConfigurationManager.ConnectionStrings("nomeconnessione").ConnectionString
Dim sqlConn As New SqlConnection(connString)
Dim sqlCmd As New SqlCommand()
Dim sqlReader As SqlDataReader
Dim NomeFile As String
Dim chkNomeFile As String



If upload.HasFile And txtDataIns.Text <> "" Then
Dim filePath As String = String.Empty

Dim di As DirectoryInfo = New DirectoryInfo(Server.MapPath("~/Import/"))
Try
If Not di.Exists Then
di.Create()
End If
Catch ex As Exception
'Response.Write(ex.Message.ToString())
Finally
End Try

Try
chkNomeFile = upload.FileName
sqlConn.Open()
sqlCmd.Connection = sqlConn
sqlCmd.CommandText = "SELECT NomeFile,Percorso FROM UpFiles WHERE NomeFile = '" & chkNomeFile & "'"
sqlReader = sqlCmd.ExecuteReader()
sqlReader.Read()
NomeFile = sqlReader("NomeFile")
If NomeFile = chkNomeFile Then
sqlReader.Close()
sqlConn.Close()
Dim message As String = "File già caricato."

Dim sb As New System.Text.StringBuilder()

sb.Append("<script type = 'text/javascript'>")

sb.Append("window.onload=function(){")

sb.Append("alert('")

sb.Append(message)

sb.Append("')};")

sb.Append("</script>")

ClientScript.RegisterClientScriptBlock(Me.GetType(), "alert", sb.ToString())
Exit Sub
End If

Catch err As Exception

sqlReader.Close()
sqlConn.Close()


Try

filePath = Path.Combine(Server.MapPath("~/Import/"), upload.FileName)
filePath = filePath.Replace(" ", "")
upload.SaveAs(filePath)

' Legge file Excel
Dim MyConnection As System.Data.OleDb.OleDbConnection

Dim DtSet As System.Data.DataSet
Dim MyCommand As System.Data.OleDb.OleDbDataAdapter

Dim dt As DataTable
Dim dr As DataRow


Dim CognomeNome As String
Dim CodFisc As String
Dim DataNascita As Date
Dim CodiceSedeInps As String
Dim NomeSedeInps As String
Dim Residenza As String
Dim CodicePatronato As String
Dim UfficioPatronato As String
Dim Patronato As String
Dim Domanda1 As String
Dim sqlstring As String


MyConnection = New System.Data.OleDb.OleDbConnection("Provider=Microsoft.ACE.OLEDB.12.0;Data Source='" & filePath & "';Extended Properties=""Excel 12.0;HDR=YES;""")
MyCommand = New System.Data.OleDb.OleDbDataAdapter("select * from [Foglio1$]", MyConnection)
DtSet = New System.Data.DataSet
MyCommand.Fill(DtSet, "[Foglio1$]")
dt = DtSet.Tables(0)
MyConnection.Close()
If dt.Rows.Count > 0 Then
Dim i As Integer
For i = 0 To dt.Rows.Count - 1
dr = dt.Rows(i)

CodFisc = dt.Rows(i).Item(6)
Domanda1 = dt.Rows(i).Item(11)

Using sqlCon As New SqlConnection(conn)
sqlstring = "SELECT CodiceFiscale,Domanda FROM Clienti WHERE CodiceFiscale = '" & CodFisc & "' AND Domanda = '" & Domanda1 & "'"
Using cmd As New SqlCommand()
cmd.CommandTimeout = 3600
cmd.CommandText = sqlstring
cmd.Connection = sqlCon
sqlCon.Open()
Dim da As New SqlDataAdapter(cmd)
Dim dt1 As New DataTable()
da.Fill(dt1)
If dt1.Rows.Count = 0 Then

CognomeNome = dt.Rows(i).Item(5)

CodFisc = dt.Rows(i).Item(6)

If dt.Rows(i).Item(7) IsNot DBNull.Value Then
DataNascita = dt.Rows(i).Item(7)
Else
DataNascita = "01/01/2000"
End If
If dt.Rows(i).Item(2) IsNot DBNull.Value Then
CodiceSedeInps = dt.Rows(i).Item(2)
Else
CodiceSedeInps = ""
End If

Domanda1 = dt.Rows(i).Item(11)


If dt.Rows(i).Item(3) IsNot DBNull.Value Then
NomeSedeInps = dt.Rows(i).Item(3)
Else
NomeSedeInps = ""
End If

If dt.Rows(i).Item(12) IsNot DBNull.Value Then
Residenza = dt.Rows(i).Item(12)
Else
Residenza = ""
End If

If dt.Rows(i).Item(13) IsNot DBNull.Value Then
CodicePatronato = dt.Rows(i).Item(13)
Else
CodicePatronato = ""
End If
If dt.Rows(i).Item(14) IsNot DBNull.Value Then
UfficioPatronato = dt.Rows(i).Item(14)
Else
UfficioPatronato = ""
End If
If dt.Rows(i).Item(15) IsNot DBNull.Value Then
Patronato = dt.Rows(i).Item(15)
Else
Patronato = ""
End If

' FUNZIONE CHE INSERISCE FISICAMENTE IL CLIENTE NEL DATABASE
InserisciCli(CognomeNome, CodFisc, DataNascita, CodiceSedeInps, NomeSedeInps, Residenza, CodicePatronato, UfficioPatronato, Patronato, Domanda1)

End If
sqlCon.Close()
End Using
End Using
Next

End If

Catch ex As Exception
Response.Write(ex.Message.ToString())
Return
End Try



' Inserisce i dati del file fisico nel database
Try
Dim strFile As String = filePath.Substring(filePath.LastIndexOf("\"))
Dim strFileName As String = strFile.Remove(0, 1)
Dim strFilePath As String = "~/Import/" & strFileName
Dim cmd As New SqlCommand("Insert into UpFiles (DataFile,Nomefile,Percorso,Ident) values (@Datafile,@Nomefile,@Percorso,@Ident)")
cmd.Parameters.AddWithValue("@DataFile", DataInserimento)
cmd.Parameters.AddWithValue("@NomeFile", strFileName)
cmd.Parameters.AddWithValue("@Percorso", strFilePath)
cmd.Parameters.AddWithValue("@Ident", chkNomeFile)
cmd.CommandTimeout = 3600
cmd.Connection = con
con.Open()
cmd.ExecuteNonQuery()
Catch ex As Exception
MsgBox(ex.Message)
Finally
con.Close()
mostra()
End Try

Finally
sqlConn.Close()
'Response.Redirect("~/upload.aspx")
End Try
Else
lblError.Text = "Campo Obbligatorio"
End If
End Sub

****** FUNZIONE CHIAMATA PER INSERIRE I CLIENTI NEL DATABASE

Public Sub InserisciCli(ByRef CognNom As String, ByRef CF As String, ByRef Nascita As Date, ByRef CodSedeInps As String, ByRef SedeInps As String, ByRef Resid As String, ByRef CodPatr As String, ByRef UffPatr As String, ByRef Patr As String, ByRef Domand As String)
Dim isupdated As Boolean
Using sqlCon As New SqlConnection(conn)
Using cmd As New SqlCommand()
cmd.CommandText = "Insert into Clienti ([CognomeNome],[CodiceFiscale],[DataNascita],[CodiceSedeInps],[NomeSedeInps],[ComResidenza],[CodicePatronato],[UfficioPatronato],[Patronato],[Domanda]) VALUES (@CognomeNome,@CodFisc,@Nascita,@CodSedeInps,@SedeInps,@Resid,@CodPatr,@UffPatr,@Patr,@Domanda)"

' Dim sqlstring1 As String = "Insert into Clienti ([Matricola],[Sede],[RagioneSociale],[Indirizzo],[Cap],[Prov],[Comune],[Settore],[CSC],[CodFiscale],[PIva],Assegnatario,Assegnata) VALUES (@Matricola,@Sede,@RagSoc,@Indirizzo,@Cap,@Prov,@Comune,@Settore,@CSC,@CodFisc,@Piva,@Assegnatario,@Assegnata)"

' Sql1.InsertCommandType = SqlDataSourceCommandType.Text
'Sql1.InsertCommand = sqlstring1
cmd.Parameters.AddWithValue("CognomeNome", CognNom)
cmd.Parameters.AddWithValue("CodFisc", CF)
cmd.Parameters.AddWithValue("Nascita", Nascita)
cmd.Parameters.AddWithValue("CodSedeInps", CodSedeInps)
cmd.Parameters.AddWithValue("SedeInps", SedeInps)
cmd.Parameters.AddWithValue("Resid", Resid)
cmd.Parameters.AddWithValue("CodPatr", CodPatr)
cmd.Parameters.AddWithValue("UffPatr", UffPatr)
cmd.Parameters.AddWithValue("Patr", Patr)
cmd.Parameters.AddWithValue("Domanda", Domand)
cmd.CommandTimeout = 3600
cmd.Connection = sqlCon
sqlCon.Open()
isupdated = cmd.ExecuteNonQuery() > 0
sqlCon.Close()
' Sql1.Insert()
'Sql1.InsertParameters.Clear()
End Using
End Using
End Sub
10.904 messaggi dal 09 febbraio 2002
Contributi
Ciao Giuseppe,
dovresti scrivere qualcosa su un file di testo per tenere traccia di ciò che sta succedendo.
Per esempio, prendiamo il ciclo for più esterno, quello in cui cicli le righe del file excel:

For i = 0 To dt.Rows.Count - 1

Subito dentro il ciclo, aggiungi una riga a un file di testo comprendente i vari valori letti dal file excel.

Poi, a procedura terminata, vai a vedere il file di testo per capire se sono presenti tutte le righe che ti aspetti di trovare.
In alternativa al file di testo, puoi usare un banale Response.Write per vedere l'output nella pagina.

Può darsi che il tuo codice stia uscendo prematuramente dal ciclo For a causa di un'eccezione. Logga anche quella su file.
Vedo che hai messo questo codice:

Catch ex As Exception
Response.Write(ex.Message.ToString())

Nella pagina non ti compare nessun errore?

ciao,
Moreno

Enjoy learning and just keep making
6 messaggi dal 17 settembre 2015
Ciao Moreno, innanzitutto grazie per la risposta. Dunque, relativamente al for per ciclare le righe di excel questo funziona bene perchè proprio li ho messo un breakpoint e nel datatable ci sono tutte le 79504 righe per cui do per scontato che il datatable dell'excel è corretto. Infatti il problema me lo da dopo. E' come se fosse che raggiunge un massimo di righe (nel mio caso circa 15000) e va in timeout e non va oltre. Ma la cosa più strana e che se lancio l'applicazione con visual studio e faccio la stessa operazione sul mio database sql locale funziona correttamente.Per cui tenderei ad escludere il lato codice. C'è qualcosa che mi sfugge sui server di produzione dove forse dovrei intervenire su qualche parametro ma non ho la più pallida idea di cosa dovrei fare. Qualcosa su IIS ? Qualcosa sul web config ? Mah... Incredibile.... ALtre idee ?
Grazie,
Giuseppe
10.904 messaggi dal 09 febbraio 2002
Contributi
Per ora non sono molto convinto che si tratti di un timeout perché ne avresti evidenza. Di solito si verifica un errore tipo "Request timed out" come quello che vedi qui.
Inoltre, il timeout di default è di 1:50 minuti mentre invece hai detto che l'operazione si completa in 40 secondi.

Probabilmente può essere velocizzata ulteriormente se correggi questo:
For i = 0 To dt.Rows.Count - 1
dr = dt.Rows(i)

CodFisc = dt.Rows(i).Item(6)
Domanda1 = dt.Rows(i).Item(11)

Using sqlCon As New SqlConnection(conn)
sqlstring = "SELECT CodiceFiscale,Domanda FROM Clienti WHERE CodiceFiscale = '" & CodFisc & "' AND Domanda = '" & Domanda1 & "'"
Using cmd As New SqlCommand()
cmd.CommandTimeout = 3600
cmd.CommandText = sqlstring
cmd.Connection = sqlCon
sqlCon.Open()


Stai ricreando una nuova connessione per ogni riga del file excel. Dovresti riusare lo stesso oggetto SqlConnection perché aprire una connessione non ha un costo trascurabile e tu lo stai pagando 80.000 volte. Inoltre, potresti preparare anche il SqlCommand che usi per fare la select e renderlo parametrico come leggi qui per avere un ulteriore aumento di prestazioni.

Ti consiglio di nuovo di scrivere righe di log su un file di testo. Non ha importanza se il codice funziona bene sul tuo pc di sviluppo; bisogna andare a loggare la sua attività nel server.

ciao,
Moreno
Modificato da BrightSoul il 27 febbraio 2018 21.19 -

Enjoy learning and just keep making
6 messaggi dal 17 settembre 2015
Ciao, ti ringrazio per i consigli che sicuramente utilizzerò.... in ogni caso ho risolto e se ti dico che cosa era !... pura fantascienza !!!
Vedi questa "maledetta" riga ?

MyConnection = New System.Data.OleDb.OleDbConnection("Provider=Microsoft.ACE.OLEDB.12.0;Data Source='" & filePath & "';Extended Properties=""Excel 12.0;HDR=YES;""")

E' bastato modificarla così:

MyConnection = New System.Data.OleDb.OleDbConnection("Provider=Microsoft.ACE.OLEDB.12.0;Data Source='" & filePath & "';Extended Properties=""Excel 12.0 Xml;HDR=YES;IMEX=1""")
Sembra che quel "Xml" aggiuntivo su Excel 12.0 e il parametro IMEX=1 abbia risolto il problema. Non chiedermi come ho fatto perchè è frutto di sapere altrui che ho trovato girovagando su vari forum e che dalla disperazione ho provato e fortunatamente è andata positiva.

Ho provato decine di volte a caricare il file e impiega circa 10min.a caricare... tempo di tutto rispetto vista la mole di dati. In ogni caso utilizzerò quanto mi hai consigliato per velocizzare ulteriormente.
Spero che serva ad altri visto che ci ho perso 1 giorno e mezzo per risolvere.

Grazie mille per tutto.
A buon rendere.
Giuseppe
10.904 messaggi dal 09 febbraio 2002
Contributi
Ok Giuseppe, grazie per aver condiviso la soluzione.
Ormai hai risolto ma eventualmente, se ti dovesse dare altri problemi, puoi leggere i file excel usando la libreria NPOI. Qui c'è un esempio.
http://forum.aspitalia.com/forum/post/409182/Libreria-NPOI.aspx

Enjoy learning and just keep making
6 messaggi dal 17 settembre 2015
Grazie... darò comunque un&#8217;occhiata....

Ciao

Torna al forum | Feed RSS

ASPItalia.com non è responsabile per il contenuto dei messaggi presenti su questo servizio, non avendo nessun controllo sui messaggi postati nei propri forum, che rappresentano l'espressione del pensiero degli autori.