Answered problema wcf accessi contemporanei

  • Thursday, November 12, 2009 5:25 PM
     
      Has Code
    Ciao a tutti!
    la mia applicazione WCF / ASP.NET manifesta un problema piuttosto grave (è la prima applicazione che faccio di questo tipo). Una decina di magazzinieri accedono più o meno contemporaneamente al database access, consultano e modificano le proposte d'ordine a loro indirizzate. Quando ci sono più accessi contemporanei ogni tanto capita un fatto increscioso: mentre il magazziniere sta consultando una proposta d'ordine, si ritrova sotto gli occhi la proposta di un altro magazziniere.
    L'applicazione è costiuita da 2 parti: un service WCF ospitato su IIS in un computer interno alla rete aziendale con Vista Business com s.o. e un'applicazione ASP.NET ospitata su aruba che interroga il service.
    Dato che l'errore si presenta quando l'applicazione ASP.NET chiede al service di trasmettergli una proposta (ne restituisce un'altra), per quel che posso capire le cause possono essere 2: dato che il nome nella proposta è preso da una variabile memorizzata nella cache, può essere che questa variabile venga sovrascritta. Oppure il service WCF  quando ci sono più accessi contemporanei impazzisce e trasmette una proposta al posto di un'altra (mi sembra più improbabile).

    Potreste aiutarmi a trovare il bandolo della matassa?
    Pileggi

    Questo è il codice con cui effettuo la richiesta e trasmetto i dati:

    LATO APPLICAZIONE ASP.NET (ARUBA)
        Private Property VNomePro() As String
            Get
                Dim s As String = Cache("VNomePro")
                Return s
            End Get
            Set(ByVal value As String)
                Cache("VNomePro") = value
            End Set
        End Property
    
        ' Pro è la collection di dati con la proposta
        Dim p As Pro = TPclient.TrasmettiPro(VNomePro)




    LATO SERVICE WCF

    ' prelevo i dati dal database access
        Public Function TrasmettiPro(ByVal sPro As String) As Pro _
            Implements ITPro.TrasmettiPro
            Dim p As New List(Of SingleRowPro)
            Dim srp As SingleRowPro
            Using cn As New OleDbConnection(sConn)
                Dim sQuery As String = String.Format("SELECT {0}.* FROM {0} ORDER BY " & _
                    "{0}.Aggiunta, {0}.Articolo;", sPro)
                Using cm As New OleDbCommand(sQuery, cn)
                    cn.Open()
                    Using rd As OleDbDataReader = cm.ExecuteReader()
                        While rd.Read()
                            srp = New SingleRowPro
                            srp.Reparto = rd.Item("Reparto")
                            srp.Precodice = rd.Item("Precodice")
                            If Not IsDBNull(rd.Item("Fatto")) Then srp.Fatto = rd.Item("Fatto")
                            srp.Articolo = rd.Item("Articolo")
                            srp.datcon = rd.Item("datcon")
                            If Not IsDBNull(rd.Item("Giacenza")) Then srp.Giacenza = rd.Item("Giacenza")
                                                    p.Add(srp)
    
                            '... e così via tutti gli altri dati
                        End While
                        rd.Close()
                    End Using
                End Using
                cn.Close()
            End Using
            Dim pp As New Pro With {.Proposta = p}
            Return pp
        End Function

All Replies

  • Thursday, November 12, 2009 11:15 PM
     
     
    In mancanza di una soluzione certa, per ora ho provato a cambiare la modalità di memorizzazione della variabili nell'applicazione ASP.NET, prima usavo la cache - Cache("NomeVariabile") - adesso uso il ViewState - ViewState("NomeVariabile"). Soltanto domani potrò sapere se il cambiamento è stato efficace perchè potrò provare più accessi contemporanei. Ma (please) aiutatemi a usare correttamente la cache, in rete si afferma che migliora sensibilmente le prestazioni!
    Pileggi
  • Friday, November 13, 2009 10:08 AM
     
     Answered
    Sicuramente il problema è proprio lì. Tieni presente che la cache è condivisa tra tutte le sessioni attive. Ti permette sostanzialmente di memorizzare dati comuni a tutte le sessioni per un più rapido accesso. Per i dati relativi alla sessione utente c'è la Session (in memoria) o il ViewState (memorizzato nella pagina). Quest'ultimo, però, tende spesso a diventare troppo grande, incrementando notevolmente il flusso di dati che viaggia dal browser al server e di conseguenza decrementando le prestazioni.
    Spero di esserti stato d'aiuto.

    Fabio Cozzolino Blogs: http://dotnetside.org/blogs/fabio http://weblogs.asp.net/fabio
    • Marked As Answer by pileggi Friday, November 13, 2009 10:44 AM
    •  
  • Friday, November 13, 2009 10:39 AM
     
     
    Grazie tante veramente. Vista la tua gentilezza vorrei chiederti ancora 2 cose:
    in quali casi è opporuno usare la cache per memorizzare i dati?
    il viewstate serializza i dati e li deserializza quando è il momento di leggerli. Questo comporta un calo di prestazioni, se i dati non sono critici, è possibile (e conveniente) salvare i dati senza serializzarli? E possibile serializzare alcui dati e non altri?
    Spero non siano troppe domande, avrei bisogno di farmi un'idea più precisa.
    Grazie ancora,
    Pileggi
  • Friday, November 13, 2009 5:18 PM
     
     Answered
    Il viewstate memorizza i dati serializzati. Il problema non si pone, se la tua classe che metti nel view state non è serializzabile becchi un'eccezione. La cache va utilizzata quando vuoi condividere dati (ma anche pezzi di output HTML) tra gli utenti e far in modo che dopo un certo periodo possano scadere. Il viewstate serve solo per mantenere informazioni tra un post-back ed il successivo. La sessione memorizza info (che non scadono mai finchè la sessione è valida) visibile solo dall'utente che li ha messi. Application memorizza dati visibili da tutti e senza scadenza (almeno fino a che non fai un reset di IIS).
    • Marked As Answer by pileggi Saturday, November 14, 2009 8:58 AM
    •  
  • Saturday, November 14, 2009 8:59 AM
     
     
    Grazie!!
  • Saturday, November 14, 2009 7:32 PM
     
     

    Conclusione di questo episodio:
    la pagina di login passa all'altra pagina la stringa contenente il nome-utente tramite un cookie (è utile perchè resta memorizzato sul browser del client e l'utente non è costretto a riscriverlo ogni volta)

    Private Property CUtente() As String
        Get
            Dim s As String = ""
            If Request.Cookies("CUtente") IsNot Nothing Then
                If Request.Cookies("CUtente")("Valore") IsNot Nothing Then
                    s = Request.Cookies("CUtente")("Valore")
                End If
            End If
            CUtente = s
        End Get
        Set(ByVal value As String)
            If Value Is Nothing Then
                If Request.Cookies("CUtente") IsNot Nothing Then
                    Dim myCookie As HttpCookie
                    myCookie = New HttpCookie("CUtente")
                    myCookie.Expires = DateTime.Now.AddDays(-1D)
                    Response.Cookies.Add (myCookie)
                End If
            Else
                Dim myCookie As HttpCookie = New HttpCookie("CUtente")
                myCookie("Valore") = Value
                myCookie.Expires = Now.AddMonths(12)
                Response.Cookies.Add (myCookie)
            End If
        End Set
    End Property

    l'altra pagina riceve l'utente dal cookie, lo memorizza nel ViewState e, tramite la stringa-utente memorizzata nel ViewState, crea tutte le altre variabili nella cache assegnandogli una chiave univoca contentente il nome-variabile e la stringa-utente:

    Private Property SUtente() As String
        Get
            Dim s As String = ViewState("SUtente")
            Return s
        End Get
        Set(ByVal value As String)
            ViewState("SUtente") = Value
        End Set
    End Property

    Private Property NomeVariabile() As String
        Get
            Dim s As String = Cache("NomeVariabile" & SUtente)
            Return s
        End Get
        Set(ByVal value As String)
            Cache("NomeVariabile" & SUtente) = Value
        End Set
    End Property

    Non so se era la cosa migliore da fare, so che in questo modo si ottiene un miglioramento di prestazioni veramente notevole rispetto a memorizzare tutte le variabili nel ViewState.
    Per questo, oltre che per dare com'è giusto conto del risultato dei consigli ricevuti, mi sento, nel mio piccolo, di consigliare a tutti questo metodo.
    Ciao!
    Pileggi