2017-12-26 17 views
1

Um C# -Programmierung zu üben, erstellt ich diese einfache SQLite Query Writer + ORM mit Microsoft.Data.SQLite und schrieb ich einige Unit-Tests (mit xunit), um sicherzustellen, Code funktioniert. Das Problem ist, wenn ich jeden Komponententest einzeln ausführe, funktioniert alles, aber wenn ich alle gleichzeitig teste, schlägt der Code fehl und sagt, dass die Datenbank gesperrt ist oder Code in Endlosschleife geht.Einfache SQLite ORM in C#, Code funktioniert, aber wie Race Condition zu lösen

Ich frage mich, ob es eine Möglichkeit gibt, den Code threadsafe mit lock(variable) {} zu machen, bin ich mir nicht sicher. Vielleicht ist etwas falsch mit der Art, wie ich Transaktionen handle (ich habe Transaktionen nur für INSERT-Anweisungen verwendet).

Dies ist die Funktion, die ich denke, ist problematisch. Jede Hilfe oder Rückmeldung würde sehr geschätzt werden.

/// <summary> 
/// Helper function that creats SQL commands 
/// </summary> 
/// <param name="commandText"></param> 
/// <returns></returns> 
private void CreateAndExecuteNonQueryCommand(string commandText) 
{ 
    if (SqliteConnection.State != ConnectionState.Open) 
    { 
     SqliteConnection.Open(); 
    } 

    var transaction = SqliteConnection.BeginTransaction(); 
    var command = SqliteConnection.CreateCommand(); 
    command.Transaction = transaction; 

    Transactions.Add(transaction); 

    try 
    {    
     command.CommandText = commandText; 
     command.ExecuteNonQuery(); 
    } 
    catch (Exception e) 
    { 
     throw new ArgumentException(e?.Message); 
    } 
    finally 
    { 
     transaction.Commit(); 
     transaction.Dispose(); 
     command.Dispose(); 
    } 
} 

Der Code ist ein wenig lang so this the link zum letzten begehen, wie ich diese Frage schreiben.

+1

Wo schließen Sie die 'SqliteConnection'? – EdSF

+0

Ich stimme zu, das ist vielleicht keine Wettlaufbedingung, aber eine Ressource wird zwischen den einzelnen Testeinheiten nicht richtig aufgeräumt. Komponententests werden in der Regel nicht parallel ausgeführt, es sei denn, dies wird ausdrücklich empfohlen, da dies zu unbeabsichtigten und schwer reproduzierbaren Nebenwirkungen führen kann. –

+0

Worauf kommt es letztendlich an, das Transaktions-Commit durchzuführen? Es ist dir egal, ob eine Ausnahme passiert ist und du trotzdem versuchen willst, dich zu verpflichten. – Evk

Antwort

1

SqliteStorage.cs enthält Methode public T RetrieveModel(Dictionary<string, object> keyValueDictionary). Dort verwenden Sie CreateCommand Methode dann rufen Sie ExecuteReader();, aber dieser Leser ist nicht geschlossen. Fügen Sie einfach diese Zeichenfolge reader.Dispose(); im unteren Bereich von RetrieveModel hinzu. Um diese Situation zu vermeiden, können Sie using blockieren. Es ruft Dispose automatisch auf.

+0

Es hat funktioniert, vielen Dank! –