C# 中的简单 SQLite ORM,代码有效,但如何解决竞争条件

Posted

技术标签:

【中文标题】C# 中的简单 SQLite ORM,代码有效,但如何解决竞争条件【英文标题】:Simple SQLite ORM in C#, code works but how to solve race condition 【发布时间】:2017-12-26 21:34:04 【问题描述】:

为了练习 C# 编程,我使用 Microsoft.Data.SQLite 创建了这个简单的 SQLite 查询编写器 + ORM,并编写了一些单元测试(使用 xunit)以确保代码正常工作。问题是当我单独运行每个单元测试时,它都可以工作,但是如果我一次都测试,代码会失败并说数据库被锁定或代码进入无限循环。

我想知道是否有办法使用lock(variable) 使代码线程安全,我不确定。也许我处理事务的方式有问题(我只将事务用于INSERT 语句)。

这是我认为有问题的功能。任何帮助或反馈将不胜感激。

/// <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();
    

代码有点长,所以this the link 写到我写这个问题时的最后一次提交。

【问题讨论】:

你在哪里关闭SqliteConnection 我同意,这实际上可能不是竞争条件,而是在每个单元测试之间没有正确清理资源。除非明确告知这样做,否则单元测试通常不会并行运行,因为它可能会导致意外且难以重现的副作用 最后做事务提交有什么意义?你不在乎是否发生了异常并想尝试提交? 【参考方案1】:

SqliteStorage.cs 包含方法public T RetrieveModel(Dictionary&lt;string, object&gt; keyValueDictionary)。在那里你使用CreateCommand 方法然后调用ExecuteReader(); 但这个阅读器没有关闭。只需在RetrieveModel 的底部添加此字符串reader.Dispose();。为避免这种情况,您可以使用using 块。它会自动调用Dispose

【讨论】:

以上是关于C# 中的简单 SQLite ORM,代码有效,但如何解决竞争条件的主要内容,如果未能解决你的问题,请参考以下文章

C#使用sqlite-net搭建简易的ORM

Android中的Sugar ORM:更新SQLite中保存的对象

Android SQLite 和数据库方案上的 ORM [关闭]

什么是最简单的Java ORM支持Sqlite?

Python教程:ORM连接Sqlite数据库,软件架构基础

C# 使用 Dapper 实现 SQLite 增删改查