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<string, object> keyValueDictionary)
。在那里你使用CreateCommand
方法然后调用ExecuteReader();
但这个阅读器没有关闭。只需在RetrieveModel
的底部添加此字符串reader.Dispose();
。为避免这种情况,您可以使用using
块。它会自动调用Dispose
。
【讨论】:
以上是关于C# 中的简单 SQLite ORM,代码有效,但如何解决竞争条件的主要内容,如果未能解决你的问题,请参考以下文章
Android中的Sugar ORM:更新SQLite中保存的对象
Android SQLite 和数据库方案上的 ORM [关闭]