11.886 messaggi dal 09 febbraio 2002
Contributi
ciao,
uhm no, così aggiungi alla lista 100 copie della stessa riga. Per evitarlo, devi avanzare alla riga successiva invocando reader.Read().

Potresti fare così, ti predisponi una lista a cui aggiungi di volta in volta le istanze di Class. Quando arriva a 100 elementi (o quando non ci sono più elementi da leggere), la serializzi.
Vado braccio, non sono sicuro della correttezza di quanto segue:
var listClass = new List<Class>();
var formatter = new BinaryFormatter();
var prossimaRigaEsiste = reader.Read()
var file = "tuo_percorso_file_bin";
using (var stream = File.OpenWrite(file)){
while (prossimaRigaEsiste)
{
  var myClass = new Class {
    c1 = reader.GetInt16(0),
    c2 = reader.GetString(1),
    c3 = reader.GetString(2),
    c4 = reader.GetString(3)
  };
  listClass.Add(myClass);
  //Valuto se esiste la prossima riga o se la mia lista è arrivata a 100 elementi
  if (!(prossimaRigaEsiste = reader.Read()) || listClass.Count == 100){
    formatter.Serialize(stream, myClassList);   
    listClass.Clear();
  }
}
}

Così aggiungi al file dei blocchi di dati binari che contengono una lista da 100 elementi (o meno, se l'ultimo blocco ne conteneva di meno).
In questo modo potrai aggiungere vari oggetti (le liste da 100) nello stesso file.
Il BinaryFormatter è in grado, automaticamente, di capire dove finisce ciascun blocco, quindi ogni volta che invochi il Deserialize gli farai deserializzare uno di quei blocchetti.
Continua ad invocare il Deserialize finché lo stream di lettura dal file non arriva alla fine.
using (var stream = File.OpenRead(file))
{
  //Questa è la lista che conterrà tutti gli oggetti
  var listClass = new List<Class>();
  var formatter = new BinaryFormatter();

  //Finché non siamo alla fine...
  while (stream.Position < stream.Length)
  {
    //Deserializzo in blocchi da 100, finché lo stream non arriva alla fine
    var listaDa100 = formatter.Deserialize(stream) as List<Class>;
    listClass.AddRange(listaDa100);
  }
}


ciao,
Moreno

Enjoy learning and just keep making
944 messaggi dal 11 febbraio 2013
No scusa ... ho scritto una cavolata...
ho corretto cosi (piu o meno quello che fai tu)

Int32 contatore = 0;  
        Int32 CAPACITY = 100;  
        List<TABELLA> listTABELLA = new List<TABELLA>(CAPACITY);  
  
        using (SqlCommand comm = new SqlCommand(select, ExportConnection))  
        {  
            using (SqlDataReader reader = comm.ExecuteReader(System.Data.CommandBehavior.SequentialAccess))  
            {  
                while (reader.Read())  
                {  
                    TABELLA myTABELLA = new TABELLA();  
  
                    myTABELLA.RoaAnno = reader.GetInt16(0);  
                      &#8230;
                    contatore++;  
                    listTABELLA.Add(myTABELLA);  
  
                    BinaryFormatter formatter = new BinaryFormatter();  
  
                    if (contatore == CAPACITY)  
                    {  
                        using (FileStream stream = new FileStream(path, FileMode.Append, FileAccess.Write))  
                        {  
                            formatter.Serialize(stream, listTABELLA);  
                        }  
                        listTABELLA.Clear();  
                        contatore = 0;  
                    }  
  
                    if (contatore > CAPACITY && listTABELLA.Count > 0)  
                    {  
                        using (FileStream stream = new FileStream(path, FileMode.Append, FileAccess.Write))  
                        {  
                            formatter.Serialize(stream, listTABELLA);  
                        }  
                    }  
                }  
                reader.Close();  


solo in deserializzazione ci mette un sacco lo stesso...come se non vedesse i blocchi da 100!!!
sono esausto :)
String path = System.Web.HttpContext.Current.Server.MapPath("~/BIN/TABELLA.bin");
        long position = 0;
        BinaryFormatter formatter = new BinaryFormatter();

        using (FileStream stream = new FileStream(path, FileMode.Open, FileAccess.Read))
        {
            while (position < stream.Length)
            {
                stream.Seek(position, SeekOrigin.Begin);
                var listTABELLA = (List<TABELLA>)formatter.Deserialize(stream);

                //position = stream.Position;

                foreach (TABELLA tabella in listTABELLA)
                {
                    tabella.InsertTABELLA(ImportConnection, tabella);
                }
            }
        }

forse il problema è il metodo InsertTABELLA che fa milioni di insert ???
Modificato da jjchuck il 22 marzo 2016 22.23 -
11.886 messaggi dal 09 febbraio 2002
Contributi

forse il problema è il metodo InsertTABELLA che fa milioni di insert ???

Certamente l'esecuzione non potrà essere rapida. Potresti avere qualche beneficio usando la classe SqlBulkCopy per inserire più oggetti in blocco (DataTable anziché liste di MyClass), ma non mi aspetterei miglioramenti di un'ordine di grandezza.

Qui il problema va preso di petto e bisogna prendere coscienza che:
  • L'operazione è di lunga durata, e non la si può velocizzare più di tanto;
  • Non si può chiedere all'utente di restare immobile in attesa per molti secondi (o minuti) prima che l'operazione si concluda;
  • E' necessario che l'operazione faccia rapporto sull'avanzamento, affinché sia anche possibile fare una stima del tempo di completamento. Questo non lo puoi fare nel contesto della richiesta di pagina, perché il server non può "sovrascrivere" il valore di una textbox, una volta che ha prodotto il codice HTML che la descrive.

Bisogna perciò tornare a fare un po' di pianificazione dato che l'approccio che stai usando adesso non è adeguato a risolvere il problema.


sono esausto :)

Ti sto per suggerire un'altro sistema che richiederà molte più energie (dato che lo affronti per la prima volta). Vedi tu se provare da solo o chiedere la collaborazione di uno sviluppatore con più esperienza.

Dato che stai deserializzando e inserendo milioni di righe, io direi di spostare questo compito al di fuori della richiesta web, per esempio in un servizio per Windows o in un job di HangFire.

Man mano che deserializzi ed inserisci i blocchetti da 100, gli fai fare rapporto ad una pagina web usando SignalR. Grazie ad esso, riuscirai a creare un canale bidirezionale tra server e client, che così potrà ricevere la percentuale di progresso man mano che avanza.

ciao,
Moreno
Modificato da BrightSoul il 22 marzo 2016 23.03 -

Enjoy learning and just keep making
944 messaggi dal 11 febbraio 2013
Hai ragione... è tutto nuovo per me ma vorrei provarci anche se sono pieno di lavoretti da fare...

spero di avere problemi di dissociazioni cognitive...stile Matrix...

speriamo bene...

ciao e grazie mille
11.886 messaggi dal 09 febbraio 2002
Contributi
Ciao,
ti linko un progetto di esempio che sfrutta Hangfire e SignalR di cui ti parlavo.
https://onedrive.live.com/redir?resid=2B0F0F6D27852B8E!15373&authkey=!AELFcWU-4fZjIQo&ithint=file%2czip

Il codice che compie l'elaborazione (che possiamo anche chiamare "job") l'ho messo in un metodo della classe "MioJobDemo", che grazie ad Hangfire andrà in esecuzione in background, al di fuori del contesto di qualsiasi richiesta web. Questo consente all'utente di spostarsi liberamente nel sito mentre l'elaborazione è in corso, e di tornare in quella pagina solo di tanto in tanto per verificare la percentuale di avanzamento che gli viene mostrata in tempo reale grazie a SignalR.

L'utente può addirittura chiudere il browser ed evitare di aspettare il completamento.
Il job può anche durare delle ore, l'importante è che IIS mantenga l'applicazione attiva e non la spenga per inattività.

ciao,
Moreno
Modificato da BrightSoul il 25 marzo 2016 22.51 -

Enjoy learning and just keep making
944 messaggi dal 11 febbraio 2013
wow...
ci ho messo un po a riconvertirlo in un sito web con vs2012...però è una figata

cmq si da solo ci avrei messo un bel po... vedo lambda expression ...operazioni asincrone...insomma robe che ho solo letto e non ancora fatte mie...

percui se ho capito sotto la classe mioJobDemo posso inizializzare le classi che rappresentano le tabelle e eseguire i metodi di serializzazione e deserializzazione che già ho giusto ?

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.