我有一个类似于以下代码的类,它需要是线程安全的。它只是一个将类实例保存/映射到数据库行的函数。
如果类实例的ID
属性为0,则认为它是一个新项 - 在这种情况下,将插入一个空行并返回其自动增量值/行ID。在此之后,行UPDATE
d,使用WHERE
子句中返回的自动增量值。
如果ID
属性大于0,则该方法仅使用UPDATE
查询。
我遇到的问题偶尔/“随机”,将创建空行或重复行。我正在努力确定原因,并且无法以我能够轻易诊断的方式可靠地重现它。
它有所有竞争条件的迹象给我,但我不明白为什么会发生这种情况 - 特别是考虑到lock
围绕方法的胆量:
有人能发现这个类/方法中的问题,还是我的问题出在其他地方?
public class clsItem
{
static clsDatabase DB;
static string TableName = "myTable";
static readonly object syncLock = new Object();
public int ID;
public string Name;
public string Description;
public bool Save()
{
lock(syncLock) {
if (ID < 0 || !(DB.ServerAvailable && DB.CredentialsAuthenticated)) return false;
bool newItem = (ID == 0) ? true : false;
long InsertID = 0;
if (newItem) // make blank row and return ID
{
if (DB.Query("INSERT INTO " + TableName + " values()", ref InsertID) == null || InsertID == 0) return false;
ID = (int)InsertID;
}
List<MySqlParameter> parameters = new List<MySqlParameter>();
FieldInfo[] props = this.GetType().GetFields(BindingFlags.Public | BindingFlags.Instance);
foreach (FieldInfo pi in props)
{
if (newItem && pi.Name == "ID")
parameters.Add(new MySqlParameter(pi.Name, InsertID));
else
parameters.Add(new MySqlParameter(pi.Name, pi.GetValue(this)));
}
string query = "UPDATE " + TableName + " SET name = @Name, desc = @Description WHERE id = @ID";
return (DB.Query(query, parameters) == null) ? false : true;
}
}
}