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