C# 在WPF应用程序中从SQL Server选择数据
在访问我正在创建的黑手党游戏的wpf应用程序中的列表时遇到问题 基本上,我阅读SQL Server 2016,然后将其添加到我的用户集合列表中。稍后,当我在显示器中使用我的列表时,它们都在那里 但是,当我使用foreach循环将temp用户设置为find username时,它只会查找硬编码的用户,而不会查找使用从SQLServer读取的数据添加的用户。我需要帮助 SQL Server读取代码:C# 在WPF应用程序中从SQL Server选择数据,c#,wpf,sql-server-2016,C#,Wpf,Sql Server 2016,在访问我正在创建的黑手党游戏的wpf应用程序中的列表时遇到问题 基本上,我阅读SQL Server 2016,然后将其添加到我的用户集合列表中。稍后,当我在显示器中使用我的列表时,它们都在那里 但是,当我使用foreach循环将temp用户设置为find username时,它只会查找硬编码的用户,而不会查找使用从SQLServer读取的数据添加的用户。我需要帮助 SQL Server读取代码: using (connect = new SqlConnection(connetionString
using (connect = new SqlConnection(connetionString))
{
connect.Open();
string readString = "select * from Users";
SqlCommand readCommand = new SqlCommand(readString, connect);
using (SqlDataReader dataRead = readCommand.ExecuteReader())
{
if (dataRead != null)
{
while (dataRead.Read())
{
tempEmail = dataRead["Email"].ToString();
tempName = dataRead["Name"].ToString();
UserCollection.addUser(tempEmail, tempName);
}
}
}
connect.Close();
}
用户集合相关部分
private static List<User> UserList = new List<User>();
// add a user
public static void addUser(string email, string name)
{
UserList.Add(new User(email, name, 0, "unset", false, false, false, false, false, false,
false, "", false, false, false, 0, 0));
}
//return list of users for use elsewhere
public static List<User> ReturnUserList()
{
return UserList;
}
列表工作的代码示例
// set listing of current players
ListOfPlayers = UserCollection.ReturnUserList();
var tempList = from player in ListOfPlayers
where player.UserBlocked == false
select new
{
Name = player.UserName,
Email = player.UserEmail,
};
this.PlayerListBox.ItemsSource = tempList;
通过我的app.xaml.cs中的foreach语句可以找到工作正常的硬编码用户添加
UserCollection.addUser("g", "Tom");
首先,您需要一个静态方法将用户添加到集合中,这有什么原因吗?即使您需要通过静态访问器访问列表,您最好在用于读取数据库的同一类上拥有静态属性 希望下面的代码片段能有所帮助
public class UserManagement {
//Static property
private static List<User> _users;
public static List<User> Users {
get {
if (_users == null) {
_user = new List<User>();
}
return _users;
}
set { }
}
//Static load method must be called before accessing Users
public static void LoadDBUsers() {
using (SqlConnection connection = new SqlConnection(connetionString)) {
connection.Open();
string readString = "select * from Users";
using (SqlCommand command = new SqlCommand(readString, connection)) {
using (SqlDataReader reader = command.ExecuteReader()) {
while (reader.Read()) {
String tempEmail = reader["Email"].ToString();
String tempName = reader["Name"].ToString();
User user = new User(tempEmail, tempName, 0, "unset", false, false, false, false, false, false, false, "", false, false, false, 0, 0));
users.Add(user);
}
}
}
}
}
}
如果您有另一个用户列表,比如来自文件的用户列表,您可以向类中添加一个loader方法,该方法将为您处理该问题
如果在某个时候需要清除用户列表,只需将其设置为新实例即可
UserManagement.Users = new List<User>();
并致电如下
List<User> dbUsers = UserManagement.LoadDBUsers();
使用后一种方法,您不需要担心代码中的多个位置维护静态属性。只需调用并将其分配给变量。
它还有一个优点,即在从静态属性访问列表之前,您总是可以从数据库中获取最新的用户列表,而不必清除并重新加载列表
不使用全局静态属性的另一个优点是,它可以避免潜在的内存问题。如果对静态属性的引用保持打开状态,则垃圾收集器很难处理静态属性。
对于实例变量,当一个变量超出范围并且不再被引用时,这是非常明显的,但是对于静态变量,引用有时在程序结束之前不会被处理
在许多情况下,这不是一个问题,但在较大的系统中,调试可能会很困难
tempEmail = dataRead["Email"].ToString();
tempName = dataRead["Name"].ToString();
tempEmail,您在上面声明的tempName
使用connect=newsqlconnectionconnectionstring
tempEmail和tempName是引用类型,因此,如果循环它的第一条记录在第二次循环之后添加,那么tempName和tempEmail值也会更新,因为它也指向相同的内存。因此,数据是重复的记录列表,因此,用户无法正确添加用户
因此,您可以更改代码
var tempEmail = dataRead["Email"].ToString();
var tempName = dataRead["Name"].ToString();
在tempEmail之前,tempName在使用语句之前删除声明
我希望这对您有所帮助。我相信是您的while循环导致了该问题。由于使用有效,全局变量tempeil和tempName保持为空。我使用MySql对代码进行了测试,这个解决方案非常有效
private List<User> PlayersList;
public Tester()
{
using (SqlConnection connect = new SqlConnection(connectionString))
{
connect.Open();
string readString = "select * from user";
SqlCommand readCommand = new SqlCommand(readString, connect);
using (SqlDataReader dataRead = readCommand.ExecuteReader())
{
if (dataRead != null)
{
while (dataRead.Read())
{
string tempEmail = dataRead["Email"].ToString();
string tempName = dataRead["Name"].ToString();
UserCollection.addUser(tempEmail, tempName);
}
}
}
connect.Close();
}
PlayersList = UserCollection.ReturnUserList();
}
public class User
{
public string email;
public string name;
// A constructor that takes parameter to set the properties
public User(string e, string n)
{
email = e;
name = n;
}
}
public static class UserCollection
{
private static List<User> UserList = new List<User>();
// add a user
public static void addUser(string email, string name)
{
UserList.Add(new User(email, name));
}
//return list of users for use elsewhere
public static List<User> ReturnUserList()
{
return UserList;
}
}
这里有很多东西没有显示出来,比如UserCollection。我可以添加更多,但整个代码集是1000行+秒,如果没有看到类的其他部分,很难看到问题可能在哪里。看起来您的实现比需要的要复杂一点——例如,使用方法返回用户列表而不是属性。我们需要的是一个最小的示例,以便在DB逻辑中调用任何变量/方法。我们需要一个可验证的示例,但不一定是所有1000多行。@DerekBlankinship如果您的UserCollection所有记录与上一条记录相同,这就是您的问题?已更新且@umasankar用户名是主键,因此不可能重叠记录?不确定我是否理解了u的意思假设这些类型是字符串并且在类中的某个地方定义为静态的,给它们赋值只会替换现有的值。是的,它们已经被定义为私有字符串。不幸的是,将它们更改为var仍然有相同的错误。我目前还没有完全完成编码,但我想我会尝试alex的答案。感谢您的帮助,我将尝试这种方法,然后很可能选中它。tempEmail和tempName都是先前声明的字符串类型。我也应该补充一点。我将尝试重写如何调用DB。所以我认为大多数时候静态输入是可以的,我想我会少用一点。这是我的默认设置,我总是这样做on@DerekBlankinship如果您需要一个单独的对象来存储一些数据,但可以从应用程序中的多个位置进行访问,我建议您查找Singleton设计模式。使用静态方法调用它,但当第一次访问时,它会创建自身的实例并返回该实例。如果已经创建了实例,静态调用将返回该实例。它仍然可能存在引用未被销毁的问题,但它更易于管理和调试。静态对象很有用,但很容易变得笨拙。
tempEmail = dataRead["Email"].ToString();
tempName = dataRead["Name"].ToString();
var tempEmail = dataRead["Email"].ToString();
var tempName = dataRead["Name"].ToString();
private List<User> PlayersList;
public Tester()
{
using (SqlConnection connect = new SqlConnection(connectionString))
{
connect.Open();
string readString = "select * from user";
SqlCommand readCommand = new SqlCommand(readString, connect);
using (SqlDataReader dataRead = readCommand.ExecuteReader())
{
if (dataRead != null)
{
while (dataRead.Read())
{
string tempEmail = dataRead["Email"].ToString();
string tempName = dataRead["Name"].ToString();
UserCollection.addUser(tempEmail, tempName);
}
}
}
connect.Close();
}
PlayersList = UserCollection.ReturnUserList();
}
public class User
{
public string email;
public string name;
// A constructor that takes parameter to set the properties
public User(string e, string n)
{
email = e;
name = n;
}
}
public static class UserCollection
{
private static List<User> UserList = new List<User>();
// add a user
public static void addUser(string email, string name)
{
UserList.Add(new User(email, name));
}
//return list of users for use elsewhere
public static List<User> ReturnUserList()
{
return UserList;
}
}
while (dataRead.Read())
{
//Set local variable during while loop
string tempEmail = dataRead["Email"].ToString();
string tempName = dataRead["Name"].ToString();
UserCollection.addUser(tempEmail, tempName);
}