C# 控制台写入线(v); } } }

C# 控制台写入线(v); } } },c#,mysql,oop,sqldatareader,mysqldatareader,C#,Mysql,Oop,Sqldatareader,Mysqldatareader,我所尝试的: -使用getstring -使用索引而不是列名 -指定特定的列名 -使用while(reader.Read) -请求不同的列数 我在登录部分使用了这个方法,它在那里工作得非常好(下面的代码)。我不明白为什么它在这里不起作用(上面的代码) 静态布尔登录(MySqlConnection-conn) { 控制台。写入(“用户名:”; 字符串username=Console.ReadLine(); 控制台。写入(“密码:”); 字符串密码=Console.ReadLine(); strin

我所尝试的: -使用getstring -使用索引而不是列名 -指定特定的列名 -使用while(reader.Read) -请求不同的列数

我在登录部分使用了这个方法,它在那里工作得非常好(下面的代码)。我不明白为什么它在这里不起作用(上面的代码)

静态布尔登录(MySqlConnection-conn)
{
控制台。写入(“用户名:”;
字符串username=Console.ReadLine();
控制台。写入(“密码:”);
字符串密码=Console.ReadLine();
string query=“从username=@username的用户中选择用户标识、用户名、密码”;
字典变量=新字典
{
[“@username”]=用户名
};
MySqlDataReader=SQLControler.SqlQuery(conn,query,vars,0);
布尔有效登录=有效登录(读卡器、密码);
返回(有效登录);
}
静态布尔ValidLogin(MySqlDataReader,字符串密码)
{
布尔返回值;
if(reader.Read())
{
//目前只返回原样的密码,稍后我将实现哈希
password=PasswordHash(密码);
if(password==reader[“password”].ToString())
{
MainProgram.user_id=Convert.ToInt32(读卡器[“user_id]”);
返回值=真;
}
其他的
{
返回值=false;
}
}
其他的
{
返回值=false;
}
reader.Close();
返回值;
}
问题在于:

string args=“”;
对于(int i=0;i
这将生成一个如下所示的查询:

从user\u id=@user\u id的用户中选择@user\u名字、@user\u姓氏、@user\u角色、@user\u状态;
同时,
vars.Add(“@”+vals[i],vals[i])
最终将查询的
@user\u forename
映射到
MySqlParameterCollection
中的
“user\u forename”
。查询最后为数据库中的每一行选择这些参数的(常量)值

解决办法是:

  • 不要在选择的列名前加上
    @
  • 不要将列名作为变量添加到查询中
  • 您可以将整个循环替换为:

    string args=string.Join(“,”,vals);
    
    您只获得列名,因为查询没有找到任何与筛选器匹配的数据(其中)。请尝试删除“从何处获取所有数据”。然后检查过滤器,查看是否有数据行与过滤器匹配。经常出现这样的问题,因为您正在连接到不同版本的数据库。因此,在调查其他问题之前,让我们先确保数据在数据库中。我删除了where子句,同样的事情也发生了,只是恢复了列名,我还尝试将查询直接提交到sql中,并得到了正确的结果。我确定我正在连接正确的数据库等。。。由于我使用的连接与我登录时使用的连接相同,因此默认数据库可能错误,或者凭据可能不正确。你应该在c#中得到与直接查询相同的结果。但如果这是问题所在,那么肯定会在程序的第一部分中出现,但这非常有效更新-我切换了选择。。。要选择*(手动未参数化)且该操作有效,则必须与未识别的参数有关,或者与那些线绞有关,从而将其修复。
    namespace Library_application
    {
        class MainProgram
        {
            public static Int32 user_id;
    
            static void Main()
            {
                MySqlConnection conn = LoginProgram.Start();
                //this is the login process and works perfectly fine so i won't show its code
                if (conn != null)
                {
                    //this is where things start to break
                    NewUser(conn);
                }
                Console.ReadLine();
            }
    
            static void NewUser(MySqlConnection conn)
            {
                //three types of users, currently only using student
                string query = "SELECT user_role FROM Users WHERE user_id=@user_id";
                Dictionary<string, string> vars = new Dictionary<string, string>
                {
                    ["@user_id"] = user_id.ToString()
                };
                MySqlDataReader reader = SQLControler.SqlQuery(conn, query, vars, 0);
    
                if (reader.Read())
                {
                    string user_role = reader["user_role"].ToString();
                    reader.Close();
    
                    //this works fine and it correctly identifies the role and creates a student
                    Student user = new Student(conn, user_id);
                    //later i will add the logic to detect and create the other users but i just need this to work first
                }
                else
                {
                    throw new Exception($"no user_role for user_id - {user_id}");
                }
    
            }
    
        }
    
        class SQLControler
        {
            public static MySqlDataReader SqlQuery(MySqlConnection conn, string query, Dictionary<string, string> vars, int type)
            {
                MySqlCommand cmd = new MySqlCommand(query, conn);
                int count = vars.Count();
                MySqlParameter[] param = new MySqlParameter[count];
                //adds the parameters to the command
                for (int i = 0; i < count; i++)
                {
                    string key = vars.ElementAt(i).Key;
                    param[i] = new MySqlParameter(key, vars[key]);
                    cmd.Parameters.Add(param[i]);
                }
                //runs this one
                if (type == 0)
                {
                    Console.WriteLine("------------------------------------");
                    return cmd.ExecuteReader();
                    //returns the reader so i can get the data later and keep this reusable
                }
    
                else if (type == 1)
                {
                    cmd.ExecuteNonQuery();
                    return null;
                }
                else
                {
                    throw new Exception("incorrect type value");
                }
    
            }
    
        }
    
        class User
        {
            public List<string> GetValues(MySqlConnection conn, List<string> vals, int user_id)
            {
    
                Dictionary<string, string> vars = new Dictionary<string, string> { };
                //------------------------------------------------------------------------------------
                //this section is generating the query and parameters 
                //using parameters to protect against sql injection, i know that it ins't essential in this scenario
                //but it will be later, so if i fix it by simply removing the parameterisation then im just kicking the problem down the road
                string args = "";
                for (int i = 0; i < vals.Count(); i++)
                {
                    args = args + "@" + vals[i];
                    vars.Add("@" + vals[i], vals[i]);
                    if ((i + 1) != vals.Count())
                    {
                        args = args + ", ";
                    }
                }
                string query = "SELECT " + args + " FROM Users WHERE user_id = @user_id"; 
                Console.WriteLine(query);
                vars.Add("@user_id", user_id.ToString());
                //-------------------------------------------------------------------------------------
    
    
    
                //sends the connection, query, parameters, and query type (0 means i use a reader (select), 1 means i use non query (delete etc..))
                MySqlDataReader reader = SQLControler.SqlQuery(conn, query, vars, 0);
    
                List<string> return_vals = new List<string>();
                if (reader.Read())
                {
                    //loops through the reader and adds the value to list
                    for (int i = 0; i < vals.Count(); i++)
                    {
                        //vals is a list of column names in the ame order they will be returned
                        //i think this is where it's breaking but im not certain
                        return_vals.Add(reader[vals[i]].ToString());
                    }
    
                    reader.Close();
                    return return_vals;
    
                }
                else
                {
                    throw new Exception("no data");
                }
    
            }
    
        }
    
    
        class Student : User
        {
    
            public Student(MySqlConnection conn, int user_id)
            {
                Console.WriteLine("student created");
                //list of the data i want to retrieve from the db
                //must be the column names
                List<string> vals = new List<string> { "user_forename", "user_surname", "user_role", "user_status"};
                //should return a list with the values in the specified columns from the user with the matching id
                List<string> return_vals = base.GetValues(conn, vals, user_id);
    
                //for some reason i am getting back the column names rather than the values in the fields
                foreach(var v in return_vals)
                {
                    Console.WriteLine(v);
                }
    
            }
    
        }
    
        static Boolean Login(MySqlConnection conn)
        {
    
            Console.Write("Username:   ");
            string username = Console.ReadLine();
            Console.Write("Password:   ");
            string password = Console.ReadLine();
    
            string query = "SELECT user_id, username, password FROM Users WHERE username=@username";
            Dictionary<string, string>  vars = new Dictionary<string, string>
            {
                ["@username"] = username
            };
            MySqlDataReader reader = SQLControler.SqlQuery(conn, query, vars, 0);
    
            Boolean valid_login = ValidLogin(reader, password);
    
    
            return (valid_login);
        }
        static Boolean ValidLogin(MySqlDataReader reader, string password)
        {
            Boolean return_val;
            if (reader.Read())
            {
                //currently just returns the password as is, I will implement the hashing later
                password = PasswordHash(password);
    
                if (password == reader["password"].ToString())
                {
                    MainProgram.user_id = Convert.ToInt32(reader["user_id"]);
                    return_val = true;
                }
                else
                {
                    return_val = false;
                }
            }
            else
            {
                return_val = false;
            }
            reader.Close();
            return return_val;
    
        }