Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/mysql/68.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 数据库保存功能出现故障的可能原因_C#_Mysql_Thread Safety - Fatal编程技术网

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

C# 数据库保存功能出现故障的可能原因,c#,mysql,thread-safety,C#,Mysql,Thread Safety,我有一个类似于以下代码的类,它需要是线程安全的。它只是一个将类实例保存/映射到数据库行的函数 如果类实例的ID属性为0,则认为它是一个新项-在这种情况下,将插入一个空行,并返回其自动增量值/行ID。接下来,使用WHERE子句中返回的自动增量值更新行 如果ID属性大于0,则该方法仅使用更新查询 我遇到的问题是偶尔/随机的,会创建空行或重复行。我正在努力确定原因,无法以一种我可以轻松诊断的方式可靠地重现它 对我来说,它有各种比赛条件的迹象,但我不明白为什么会发生这种情况——特别是考虑到围绕着方法的核

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

如果类实例的ID属性为0,则认为它是一个新项-在这种情况下,将插入一个空行,并返回其自动增量值/行ID。接下来,使用WHERE子句中返回的自动增量值更新行

如果ID属性大于0,则该方法仅使用更新查询

我遇到的问题是偶尔/随机的,会创建空行或重复行。我正在努力确定原因,无法以一种我可以轻松诊断的方式可靠地重现它

对我来说,它有各种比赛条件的迹象,但我不明白为什么会发生这种情况——特别是考虑到围绕着方法的核心的锁:

有人能发现这个类/方法中的问题吗,或者我的问题在其他地方吗

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;
        }
    }
}

在受锁保护的块内,可以多次访问ID。设置其值的所有其他位置是否也受同步锁定的保护?使用块访问的其他字段也可能存在同样的问题。请记住,锁定的目的是控制对共享资源的访问,而不仅仅是将条目序列化到特定的代码块中。@hatchet只有当它是新行/项时,此保存函数才会更改ID,或者在类的Load方法中,我应该使用相同的同步锁来保护它吗?。由于这不是一个静态类,我看不出这将如何导致冲突的情况,因为当我看到该实例的ID是公共字段时,该实例的ID仅设置为once,这就增加了它可以在任何地方、任何时间更改的可能性,如果在执行Save时发生这种情况,那将是一个问题。但是没有看到这个类如何被使用的更大背景,我只能指出它是一个潜在的问题。如果您描述一下为什么您认为首先需要锁,也就是说,多个线程正在访问这个类的特定实例,这可能会有所帮助。我明白您的意思,我可能应该使用私有setter而不是字段将其设置为公共属性,但无论如何都不会在其他地方设置它。锁定的原因主要是一个有希望的测试,看看同一个实例被不同的线程保存是否有问题。虽然实际上,该实例可能会被其他线程读取,但对于这个特定的类,每个项在新行中只保存一次。不过,我还有其他课程遵循这种模式。