C# 在定义类的位置之外使用类

C# 在定义类的位置之外使用类,c#,asp.net,sql,scope,datareader,C#,Asp.net,Sql,Scope,Datareader,我试图让我的应用程序检查SQL数据库中的Admins表,然后获取当前用户所属部门的名称。之后,我想检查另一个表,只选择属于该部门的新闻项目 下面显示了我是如何进行的,但是问题在于在While循环之外使用mydepartment变量(在第二个SQL查询中使用) 除此之外,一切正常。任何帮助都将不胜感激 public string username = System.Web.HttpContext.Current.User.Identity.Name.Split('\\')[1]; public s

我试图让我的应用程序检查SQL数据库中的Admins表,然后获取当前用户所属部门的名称。之后,我想检查另一个表,只选择属于该部门的新闻项目

下面显示了我是如何进行的,但是问题在于在While循环之外使用mydepartment变量(在第二个SQL查询中使用)

除此之外,一切正常。任何帮助都将不胜感激

public string username = System.Web.HttpContext.Current.User.Identity.Name.Split('\\')[1];
public string mydepartment;

protected void Page_Load(object sender, EventArgs e)
{
    lblUser.Text = username.ToString();
    SqlConnection myConnection = new SqlConnection();
    myConnection.ConnectionString = @"Data Source=.\SQLEXPRESS;AttachDbFileName=|DataDirectory|\Database1.mdf;Integrated Security=True;User Instance=True";

    myConnection.Open();
    string selectretrieveSQL = ("SELECT * FROM Admins WHERE userid = '" + username.ToString() + "'");
    SqlCommand retrieveinfocmd = new SqlCommand(selectretrieveSQL, myConnection);
    SqlDataReader reader = retrieveinfocmd.ExecuteReader();

    while (reader.Read())
    {
        ListItem newItem = new ListItem();
        newItem.Text = reader["Department"].ToString();
        newItem.Value = reader["userid"].ToString();
        UserIds.Items.Add(newItem);
        mydepartment = reader["Department"].ToString();
        mydepartmentlbl.Text = reader["Department"].ToString();
    }
    reader.Close();

    string selectNewsSQL = ("SELECT * FROM NewsItems WHERE Department = '" + mydepartment + "'");
}

首先,我强烈建议您创建一些类来保存数据库对象的属性

例如,您的管理员可能如下所示:

public class Admin
{
  public string Username { get; set; }
  public string Department { get; set; }

  // .. More properties here
}
protected void Page_Load(object sender, EventArgs e)
{
  var connectionString = @"Data Source=.\SQLEXPRESS;AttachDbFileName=|DataDirectory|\Database1.mdf;Integrated Security=True;User Instance=True";

  using(var connection = InitializeDatabase(connectionString))
  {
    var admin = GetAdminsByUsername(connection, username).FirstOrDefault();

    if(admin == null)
    {
      // No admin was found, do something here.
      return;
    }

    var newItem = new ListItem();
    newItem.Text = admin.Department.
    newItem.Value = admin.Username;

    // Keep your controls named consistently, don't use shorthands
    // since you already have IntelliSense to auto-complete them for you

    usernameLabel.Text = admin.Username;
    departmentLabel.Text = admin.Department;
  }
下一步,你应该制定一些方法来为你做这些肮脏的工作。我将从数据库初始化开始:

static SqlConnection InitializeDatabase(string connectionString)
{
  var connection = new SqlConnection(connectionString);
  connection.Open();

  return connection;
}
因此,也许您有一种方法可以为您获取适当的
管理员

static IEnumerable<Admin> GetAdminsByUsername(SqlConnection connection, 
                                              string username)
{
  var adminList = new List<Admin>();

  // You really should be using stored procedures here instead...
  var query = @"SELECT * FROM Admins WHERE Username = @Username";

  using (var command = new SqlCommand(query, connection))
  {
    command.Parameters.AddWithValue("@Username", username);

    using (var reader = command.ExecuteReader())
    {
      while (reader.Read())
      {
        var adminUsername = reader["Username"].ToString();
        var adminDepartment = reader["Department"].ToString();

        var admin = new Admin
        {
          Username = adminUsername,
          Department = adminDepartment
        };

        adminList.Add(admin);
      }
      reader.Close();

      return adminList;
    }
  }
}

这至少可以让您从正确的方向开始。

首先,我强烈建议您创建一些类来保存数据库对象的属性

例如,您的管理员可能如下所示:

public class Admin
{
  public string Username { get; set; }
  public string Department { get; set; }

  // .. More properties here
}
protected void Page_Load(object sender, EventArgs e)
{
  var connectionString = @"Data Source=.\SQLEXPRESS;AttachDbFileName=|DataDirectory|\Database1.mdf;Integrated Security=True;User Instance=True";

  using(var connection = InitializeDatabase(connectionString))
  {
    var admin = GetAdminsByUsername(connection, username).FirstOrDefault();

    if(admin == null)
    {
      // No admin was found, do something here.
      return;
    }

    var newItem = new ListItem();
    newItem.Text = admin.Department.
    newItem.Value = admin.Username;

    // Keep your controls named consistently, don't use shorthands
    // since you already have IntelliSense to auto-complete them for you

    usernameLabel.Text = admin.Username;
    departmentLabel.Text = admin.Department;
  }
下一步,你应该制定一些方法来为你做这些肮脏的工作。我将从数据库初始化开始:

static SqlConnection InitializeDatabase(string connectionString)
{
  var connection = new SqlConnection(connectionString);
  connection.Open();

  return connection;
}
因此,也许您有一种方法可以为您获取适当的
管理员

static IEnumerable<Admin> GetAdminsByUsername(SqlConnection connection, 
                                              string username)
{
  var adminList = new List<Admin>();

  // You really should be using stored procedures here instead...
  var query = @"SELECT * FROM Admins WHERE Username = @Username";

  using (var command = new SqlCommand(query, connection))
  {
    command.Parameters.AddWithValue("@Username", username);

    using (var reader = command.ExecuteReader())
    {
      while (reader.Read())
      {
        var adminUsername = reader["Username"].ToString();
        var adminDepartment = reader["Department"].ToString();

        var admin = new Admin
        {
          Username = adminUsername,
          Department = adminDepartment
        };

        adminList.Add(admin);
      }
      reader.Close();

      return adminList;
    }
  }
}

这至少可以让你朝着正确的方向开始。

抛开之前海报上所说的一切,我同意所有这些,所呈现的代码将不起作用,因为在while循环期间,你所做的是用用户信息填充列表框或某种下拉列表(显示为Department,值为Userid)

如果希望能够根据部门获取更多信息,则需要处理该列表框或select的SelectedIndexChanged事件(或类似事件),获取当前选定的文本值,然后创建第二个查询并执行它

但是,请务必遵循前面海报的建议,您不必使用存储过程,但您确实应该在查询中使用参数。想象一下,如果某个讨厌的人设法传递了一个用户IDl33t';删除表管理员,会发生什么情况。然后,您的页面将执行以下操作:

SELECT * FROM Admins WHERE userid = 'l33t';drop table Admins;
哎呀…我知道在你的特殊情况下,你不接受用户输入,但迟早你会


希望这能有所帮助。

抛开之前海报上所说的一切,我同意所有这些,呈现的代码将不起作用,因为在while循环过程中,您所做的是用用户信息填充列表框或某种下拉列表(显示为Department,值为Userid)

如果希望能够根据部门获取更多信息,则需要处理该列表框或select的SelectedIndexChanged事件(或类似事件),获取当前选定的文本值,然后创建第二个查询并执行它

但是,请务必遵循前面海报的建议,您不必使用存储过程,但您确实应该在查询中使用参数。想象一下,如果某个讨厌的人设法传递了一个用户IDl33t';删除表管理员,会发生什么情况。然后,您的页面将执行以下操作:

SELECT * FROM Admins WHERE userid = 'l33t';drop table Admins;
哎呀…我知道在你的特殊情况下,你不接受用户输入,但迟早你会


希望这能有所帮助。

你不会说它是如何工作的。我清理了代码格式,看起来如果该用户名确实有数据的话,
mydepartment
应该可以正常工作。另外,还有一些注释:不要那样做SQL。使用参数化SQL。尤其是对于基于web的东西,但作为一个通用参数,总是使用参数。不要这样做连接字符串。这只是等待发生的SQL注入。另外,在3个位置执行reader[“Department”].ToString()。执行一次,将其存储在变量中并使用该变量。reader[“”]将在性能方面花费更多。最后,对于您的SQL对象,请使用using关键字。它们是一次性的,不会被使用。此外,
mydepartment
是一个字符串变量,而不是一个类。一个用户是否可以属于多个部门,即是否保证数据库查询始终只返回一行,或者是否可以r要返回多行?您不会说它是如何工作的。我清理了代码格式,如果该用户名确实有任何数据,则看起来
mydepartment
应该可以正常工作。此外,还有一些注释:不要这样做SQL。使用参数化SQL。特别是对于基于web的内容,但作为一个通用的、始终使用的参数s、 不要连接字符串。这只是等待发生的SQL注入。另外,在3个位置执行reader[“Department”]。ToString()。执行一次,将其存储在变量中并使用该变量。reader[“”]将在性能方面花费更多。最后,对于您的SQL对象,请使用using关键字。它们是一次性的,不会被使用。此外,
mydepartment
是一个字符串变量,而不是一个类。一个用户是否可以属于多个部门,即是否保证数据库查询始终只返回一行,或者是否可以r要返回多行吗?