数据库保存功能出现故障的可能原因

时间:2014-11-01 03:06:32

标签: c# mysql thread-safety

我有一个类似于以下代码的类,它需要是线程安全的。它只是一个将类实例保存/映射到数据库行的函数。

如果类实例的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;
        }
    }
}

0 个答案:

没有答案