Καλώς ορίσατε στο dotNETZone.gr - Σύνδεση | Εγγραφή | Βοήθεια
σε

 

Αρχική σελίδα Ιστολόγια Συζητήσεις Εκθέσεις Φωτογραφιών Αρχειοθήκες

Ποιος ο βέλτιστος τρόπος να περάσουμε ένα Datatable σε SQLite?

Îåêßíçóå áðü ôï ìÝëïò AlKiS. Τελευταία δημοσίευση από το μέλος AlKiS στις 06-06-2017, 13:13. Υπάρχουν 0 απαντήσεις.
Ταξινόμηση Δημοσιεύσεων: Προηγούμενο Επόμενο
  •  06-06-2017, 13:13 78108

    Ποιος ο βέλτιστος τρόπος να περάσουμε ένα Datatable σε SQLite?

    So, I was using SQL Server but there is a need for me to change to SQLite. I had the following code that worked very fast for 600.000 rows (about a minute).


        Dim SQLAdapter As New SqlDataAdapter

        Dim dtKinoDraws As New DataTable

        Dim SQLcmdBuilder As SqlCommandBuilder


        'Emptying the Database

        ExecuteSQLQuery(<SQL>

                            USE <%= DatabaseName %>

                            TRUNCATE TABLE [<%= DatabaseName %>].[dbo].<%= KinoDrawsTableName %>

                        </SQL>.Value)


        'This is so we have the SCHEMA to use dtKinoDraws.NewRow later to add the 400.000 rows

        SQLAdapter = New SqlDataAdapter(<SQL>

                                             USE <%= DatabaseName %>

                                             Select * FROM [<%= DatabaseName %>].[dbo].<%= KinoDrawsTableName %>

                                        </SQL>.Value, SQLConn)

        SQLcmdBuilder = New SqlCommandBuilder(SQLAdapter)

        SQLAdapter.Fill(dtKinoDraws)


        [Adding the 600.000+ rows to the datatable dtKinoDraws as described below]


        'Copying everything from the datatable back to SQL Server (takes about a minute)

        Using bulkCopy As New SqlBulkCopy(SQLConn)

            bulkCopy.DestinationTableName = KinoDrawsTableName

            bulkCopy.WriteToServer(item)

        End Using


        SQLAdapter.Update(dtKinoDraws)

        SQLAdapter.Dispose()

        SQLConn.Close()


    Now I tried to do the same with SQLite but there is no SQLiteBulkCopy, modelling after my previous code and after searching stock overflow for a way, I wrote this extremely inefficient and snail-slow piece of code (takes literally HOURS):


        Dim SQLiteAdapter As New SQLiteDataAdapter

        Dim dtKinoDraws As New DataTable

        Dim SQLitecmdBuilder As SQLiteCommandBuilder


        'Emptying the Database

        ExecuteSQLQuery(<SQL>

                            DELETE FROM [<%= KinoDrawsTableName %>];

                            VACUUM;

                        </SQL>.Value)


        'This is so we have the SCHEMA to use dtKinoDraws.NewRow later to add the 400.000 rows

        SQLiteAdapter = New SQLiteDataAdapter(<SQL>

                                                  Select * FROM <%= KinoDrawsTableName %>

                                              </SQL>.Value, SQLConnLite)

        SQLitecmdBuilder = New SQLiteCommandBuilder(SQLiteAdapter)


        SQLiteAdapter.Fill(dtKinoDraws)


        [Adding the 600.000+ rows to the datatable dtKinoDraws as described below]


        SQLiteAdapter.Update(dtKinoDraws)

        SQLiteAdapter.Dispose()

        SQLConnLite.Close()


    Visual Studio's Output gives me a nearly infinite number of this message at least twice a second: "SQLite notice (27): delayed 25ms for lock/sharing conflict at line 42982"


    How can I improve it to be fast like the SQL Server one?

    My code is in VB, so I'd prefer VB code, but I can translate C# ones to VB so that's cool too :)


    ===========================================================================

    Now, I didn't think that the way the records are added to the datatable plays a role as THAT only takes seconds, so to keep it succinct, I abstracted that layout of information. If it is indeed needed, here's the whole code:


        Private Async Function LoadKinoDrawsFromTextFiles(ByVal FromValue As Integer, ByVal ToValue As Integer, ByVal Files() As String, ByVal dtTable As DataTable) As Task(Of DataTable)

            Dim Result As DataTable = dtTable.Clone


            Await Task.Run(

                Sub()

                    For i As Integer = FromValue To ToValue

                        DownloadingDrawsProgress += 1

                        Dim FileContent() As String = File.ReadAllLines(Files(i))

                        Dim CurLineKinoDrawNum As Integer = -1


                        For Each line In FileContent

                            If line <> "" AndAlso line.Length > 10 Then

                                Try

                                    Dim LineDecomposition As List(Of String) = line.Split(" "c).ToList


                                    Dim NewDataRow As DataRow = Result.NewRow

                                    CurLineKinoDrawNum = CInt(LineDecomposition(0))

                                    NewDataRow(0) = CurLineKinoDrawNum

                                    Try

                                        NewDataRow(1) = Date.ParseExact(LineDecomposition(1) & " " & LineDecomposition(2), KinoDateFormat, CultureInfo.InvariantCulture)

                                    Catch ex As Exception

                                        Try

                                            NewDataRow(1) = Date.ParseExact(LineDecomposition(1) & " " & LineDecomposition(2), "d/M/yyyy HH:mm", CultureInfo.InvariantCulture)

                                        Catch exc As Exception

                                            NewDataRow(1) = Date.Parse(LineDecomposition(1) & " " & LineDecomposition(2))

                                        End Try

                                    End Try

                                    NewDataRow(2) = ArrayBox(False, " ", 0UI, False, LineDecomposition.Skip(3), True, "")

                                    Result.Rows.Add(NewDataRow)


                                Catch ex As Exception

                                    Try

                                        Dim Tries As Integer = 0

                                        Dim DownloadClient As New WebClient With {.Proxy = Nothing}

                                        Dim OnlineDrawJSONString As String

                                        Dim OnlineDrawJSON As JObject = Nothing


                                        Do Until Tries >= 10

                                            Try

                                                OnlineDrawJSONString = DownloadClient.DownloadString(DrawByNumberLink.Replace("{NumIdentifier}", CurLineKinoDrawNum.ToString))

                                                OnlineDrawJSON = JObject.Parse(OnlineDrawJSONString)

                                                Tries = 10

                                            Catch exb As Exception

                                                Thread.Sleep(2000)

                                                Tries += 1

                                            End Try

                                        Loop

                                        Tries = 0


                                        If OnlineDrawJSON Is Nothing Then Throw New Exception("Unable to download the Draw!")


                                        Dim OnlineDrawNum As Integer = OnlineDrawJSON(DrawIdentifier)(DrawNumberIdentifier).Value(Of Integer)()

                                        Dim dateStr As String = CStr(OnlineDrawJSON(DrawIdentifier)(DrawDateIdentifier))

                                        dateStr = dateStr.Substring(0, dateStr.IndexOf("T")) & " " & dateStr.Substring(dateStr.IndexOf("T") + 1, 5) '5 because it'll always be 5. e.g. "22:00".Length = 5

                                        Dim OnlineDrawDate As Date

                                        Try

                                            OnlineDrawDate = Date.ParseExact(dateStr, "dd-MM-yyyy HH:mm", CultureInfo.InvariantCulture)

                                        Catch exn As Exception

                                            Try

                                                OnlineDrawDate = Date.ParseExact(dateStr, "d-M-yyyy HH:mm", CultureInfo.InvariantCulture)

                                            Catch exc As Exception

                                                OnlineDrawDate = Date.Parse(dateStr)

                                            End Try

                                        End Try


                                        Dim OnlineResults As List(Of Integer) = OnlineDrawJSON(DrawIdentifier)(DrawResultsIdentifier).Values(Of Integer)().ToList


                                        Dim drRow As DataRow = Result.NewRow

                                        drRow(0) = OnlineDrawNum

                                        drRow(1) = OnlineDrawDate

                                        drRow(2) = ArrayBox(False, " ", 0UI, False, OnlineResults, True, "")

                                        Result.Rows.Add(drRow)


                                    Catch exc As Exception

                                        CreateCrashFile(exc, True,, MsgBoxStyle.Critical)

                                        Exit Sub

                                    End Try

                                End Try

                            End If

                        Next

                    Next

                End Sub)


            Return Result

        End Function


        Public Function ArrayBox(Of T)(ByVal doNumeriseItems As Boolean, ByVal DelimitationStr As String, ByVal SplitOnNum As UInteger, ByVal IgnoreNullValues As Boolean, ByVal IETVar As IEnumerable(Of T), Optional ByVal IgnoreDelimitSpace As Boolean = False, Optional ByVal DefaultSpace As String = " ", Optional ByVal AlwaysDelimitBeforeNewLine As Boolean = False, Optional ByVal PrefixString As String = "", Optional ByVal SuffixString As String = "", Optional DoNotPrefixIfValueIsNumeric As Boolean = False, Optional DoNotSuffixIfValueIsNumeric As Boolean = False, Optional ByVal AddTwoDoubleQuotesBeforeADoubleQuoteCharacter As Boolean = False, Optional ByVal StrInCaseOfNullValue As String = " ") As String

            Dim sbRet As New StringBuilder


            If IETVar IsNot Nothing Then

                For i = 0 To IETVar.Count - 1

                    If (IETVar(i) IsNot Nothing AndAlso Not IsDBNull(IETVar(i))) OrElse Not IgnoreNullValues Then   '   If the IEVariable is something

                        Dim StringToBeAppended As String = StrInCaseOfNullValue

                        Try

                            StringToBeAppended = IETVar(i).ToString

                        Catch ex As Exception

                        End Try


                        If doNumeriseItems Then sbRet.Append(i + 1).Append(") ") '      Numerise it if user asked it


                        If PrefixString <> "" AndAlso (Not IsNumeric(StringToBeAppended) OrElse Not DoNotPrefixIfValueIsNumeric) Then ' If there is a Prefix set, and value isnt numeric OR, is numeric but prefixing is allowed

                            sbRet.Append(PrefixString) '                                                                                then append it before the actual value

                        End If


                        If Not AddTwoDoubleQuotesBeforeADoubleQuoteCharacter Then '         If we are to proceed normally,

                            sbRet.Append(StringToBeAppended) '                              Print the Value of IETVar(i)

                        Else

                            sbRet.Append(StringToBeAppended.Replace("""", """""""")) '      Else, add 2 double-quotes before any double-quote character

                        End If


                        If SuffixString <> "" AndAlso (Not IsNumeric(StringToBeAppended) OrElse Not DoNotSuffixIfValueIsNumeric) Then 'If there is a Suffix set, and value isnt numeric OR, is numeric but suffixing is allowed

                            sbRet.Append(SuffixString) '                                                                                    then append it after the actual value

                        End If


                        If AlwaysDelimitBeforeNewLine AndAlso DelimitationStr <> "" AndAlso i <> IETVar.Count - 1 Then '       If Always Delimit And it isn't the last element of all

                            sbRet.Append(DelimitationStr) '                                                                 then Delimit it

                            If Not IgnoreDelimitSpace AndAlso (SplitOnNum = 0 OrElse (i + 1) Mod SplitOnNum <> 0) Then sbRet.Append(DefaultSpace) ' Put a space if a space should be put


                        ElseIf DelimitationStr <> "" AndAlso (SplitOnNum = 0 OrElse (i + 1) Mod SplitOnNum <> 0) AndAlso i <> IETVar.Count - 1 Then '  if it should be delimited And it isn't the last element of the line

                            sbRet.Append(DelimitationStr) '                                                                                         then Delimit it

                            If Not IgnoreDelimitSpace Then sbRet.Append(DefaultSpace) '                                                             Put a space if a space should be put

                        End If


                        If SplitOnNum <> 0 AndAlso (i + 1) Mod SplitOnNum = 0 AndAlso i <> IETVar.Count - 1 Then '  If you separate them with NewLines and it is the last element of the line

                            sbRet.AppendLine() '                                                                then append a NewLine

                        End If

                    End If

                Next


            End If


            Return sbRet.ToString

        End Function


        Public Async Sub FillDatabaseWithDefaultDraws()

        Dim SQLiteAdapter As New SQLiteDataAdapter

        Dim dtKinoDraws As New DataTable

        Dim SQLitecmdBuilder As SQLiteCommandBuilder


        'Emptying the Database

        ExecuteSQLQuery(<SQL>

                            DELETE FROM [<%= KinoDrawsTableName %>];

                            VACUUM;

                        </SQL>.Value)


        'This is so we have the SCHEMA to use dtKinoDraws.NewRow later to add the 400.000 rows

        SQLiteAdapter = New SQLiteDataAdapter(<SQL>

                                                  Select * FROM <%= KinoDrawsTableName %>

                                              </SQL>.Value, SQLConnLite)

        SQLitecmdBuilder = New SQLiteCommandBuilder(SQLiteAdapter)


        SQLiteAdapter.Fill(dtKinoDraws)

        Dim Files() As String = Directory.GetFiles(strKinoDrawsDirPath)


        Dim item = Await LoadKinoDrawsFromTextFiles(0, Files.Length - 1, Files, dtKinoDraws)

        dtKinoDraws.Merge(item)


        SQLiteAdapter.Update(dtKinoDraws)

        SQLiteAdapter.Dispose()

        SQLConnLite.Close()

        End Sub


    And here's what each file in Files(i) looks like:


    > 304454 30/11/2011 21:00 7 65 31 62 21 50 34 70 37 40 16 59 10 41 42 76 78 71 74 47


    > 304453 30/11/2011 20:55 62 30 68 63 9 45 10 50 1 78 22 6 61 52 38 2 55 26 49 72


    > 304452 30/11/2011 20:50 45 65 42 1 78 14 16 4 43 70 28 19 67 23 77 40 49 71 22 21


    > ...


    > 300971 1/11/2011 10:00 52 48 1 76 13 38 24 18 16 20 53 59 4 40 65 68 42 9 2 51


    Δημοσίευση στην κατηγορία: , , , ,
Προβολή Τροφοδοσίας RSS με μορφή XML
Με χρήση του Community Server (Commercial Edition), από την Telligent Systems