2010-11-20 8 views
1

Ich versuche, ein paar PL/SQL-Prozeduren in einer VB-App auszuführen. Die Verfahren eine Weile dauern, laufen, so will ich sie in separate Threads setzen (das Thema, von dem ich bin neu in)Füllen von Datensätzen von Oracle innerhalb von VB-Threads

Derzeit jeder Thread eine Funktion aufruft, die wiederum den folgenden Code ruft:

' Function getDataSet 
' builds a data set from given information 
' Parameters: 
' aCommand - the PL/SQL procedure to call 
' aParamCollection - an oraParameterCollection object containing all the parameters 
' aDataSet - a data set to hold the results 
' Returns: 
' number of rows retrieved 

Public Function getDataSet(_ 
    ByVal aCommand As String, _ 
    ByVal aParamCollection As oraParameterCollection, _ 
    ByRef aDataSet As DataSet _ 
    ) As Integer 

    Dim result As Integer = 0 

    ' define commands etc 
    Dim cmd As OracleCommand = New OracleCommand(aCommand, dbConn) 
    cmd.CommandType = CommandType.StoredProcedure 

    ' add parameters for the query 
    For i As Integer = 0 To aParamCollection.getParameterCount() - 1 
     cmd.Parameters.Add(New OracleParameter(_ 
           aParamCollection.getParameterByIndex(i).ParameterName, _ 
           aParamCollection.getParameterByIndex(i).ParameterType)).Value = _ 
           aParamCollection.getParameterByIndex(i).ParameterValue 
    Next 

    Dim param As OracleParameter = New OracleParameter("io_cursor", OracleDbType.RefCursor) 
    cmd.Parameters.Add(param).Direction = ParameterDirection.Output 
    CheckConnection() 
    cmd.ExecuteNonQuery() 

    Dim cur As OracleRefCursor 
    cur = param.Value 
    cmd.Dispose() 

    Dim theAdaptr As New OracleDataAdapter 

    If aDataSet IsNot Nothing Then 
     theAdaptr.Fill(aDataSet, cur) 
     result = aDataSet.Tables(0).Rows.Count 
    End If 

    Return result 

End Function 

Wo:
aCommand die PL/SQL proc =
aParamCollection = eine benutzerdefinierte Klasse auszuführen, die Parameter, Typen und Werte hält
aDataSet = die die resultierenden Datensatz Daten halten

Allerdings, wenn ich die App laufen lasse, erhalte ich eine Zugriffsverletzung an dieser Stelle:

theAdaptr.Fill(aDataSet, cur) 

Ich gehe davon aus, dass die einzelnen Fäden nicht den Anruf zur gleichen Zeit füllen machen können, ist das richtig? Ich bin zur Zeit treten jeden Thread ab, als so:

Dim th_Mean As New Thread(AddressOf getMeanData) 
    Dim th_Stdev As New Thread(AddressOf getStdevData) 

    th_Mean.Name = "th_Mean" 
    th_Stdev.Name = "th_Stdev" 

    th_Mean.Start() 
    th_Stdev.Start()  

    Do While th_Mean.IsAlive Or th_Stdev.IsAlive 
    Loop 

Letztlich meine Frage ist, was sollte ich als so tun, geschieht die Zugriffsverletzung zu vermeiden?

Vielen Dank für das Lesen BBz

Antwort

0

Haben Sie darüber nachgedacht, die Parallelität in der Datenbank hinzufügen? Parallelität ist mit deklarativem SQL (relativ) einfach. Je nach Ihren gespeicherten Prozeduren kann es so einfach sein wie die langsame Abfrage herausfinden und einen Hinweis, so etwas wie:

select /*+ parallel(my_table) */ * from my_table; 

Verfährt man mehr über Zeile-für-Zeile-Verarbeitung ist als Abfragen müssen Sie möglicherweise aussehen in parallele Pipeline-Funktionen.

+0

Thx für die Antwort. Die gespeicherten Procs, die ich verwende, sind eigentlich wie diese, die ich in einem anderen Thread gepostet habe: http://StackOverflow.com/Questions/4218345/solved-pl-sql-avg-function-with-vs2008-causing-arithmetic-operation-results -i Es wird AVG mit DECODE verwendet, um Durchschnittswerte von Daten in Spalten auf Grundlage eines bestimmten Namens zu sortieren. Das Ausführen dieser Abfrage mit Daten eines Jahres oder länger dauert> 10 Minuten (das ist unangemessen, was ich oben erreichen möchte!) – Bob

+0

Es gibt möglicherweise mehrere Möglichkeiten, diese Prozedur zu optimieren: Können Sie die gesamte Prozedur in die entfernte Datenbank? Verteilte Verarbeitung fügt eine Menge Komplexität hinzu, wenn Sie so viel von der Verarbeitung wie möglich an derselben Stelle ausführen können, die Ihnen helfen könnte. Wenn alle Tabellen lokal sind, ist das Hinzufügen von Parallelität einfach, aber ich denke nicht, dass Sie über eine Datenbankverbindung parallelisieren können. Einige der Oracle-Dokumentation impliziert, dass verteilte Tabellen in der Regel an die lokale Instanz gezogen und dort verbunden werden. Vielleicht kann der DRIVING_SITE Hinweis helfen? –

+0

Hi, danke nochmal für den Rat. Ich denke, ich kann auf das Zeichenbrett zurückgehen und die Statistiken usw. im Client-Code machen (obwohl ich dachte, der ganze Punkt wäre, die DB zu benutzen, um die Arbeit zu machen!) Ich glaube nicht, dass ich die Möglichkeit habe, die Procs zu setzen in die primäre DB und um ehrlich zu sein, habe ich keine Hinweise zuvor verwendet, so dass das wie eine Lernkurve an sich scheint (was ich nicht abgeneigt bin, aber dringendere Dinge mit diesem Projekt zu konzentrieren haben.) – Bob

Verwandte Themen