C# 在WPF应用程序中从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

在访问我正在创建的黑手党游戏的wpf应用程序中的列表时遇到问题

基本上,我阅读SQL Server 2016,然后将其添加到我的用户集合列表中。稍后,当我在显示器中使用我的列表时,它们都在那里

但是,当我使用foreach循环将temp用户设置为find username时,它只会查找硬编码的用户,而不会查找使用从SQLServer读取的数据添加的用户。我需要帮助

SQL Server读取代码:

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