【问题标题】:datareader doesn't read datadatareader 不读取数据
【发布时间】:2015-05-13 21:59:09
【问题描述】:

我有一点问题,但我无法弄清楚问题所在。所以我有一个DataReader,我从我的数据库中读取我的数据。但问题是,尽管我的数据库中有匹配的行,DataReader 仍然没有任何行返回。

我的数据库连接:

static private String _connectionString = @"Data Source=(localdb)\v11.0;Initial Catalog=dboVids;User id=g;password=g;Connect Timeout=15;Encrypt=False";  
        static private SqlConnection _connection;

        static Connection()
        {
            try
            {
                _connection = new SqlConnection(_connectionString);
                Open();
            }
            catch (Exception ex)
            {
                switch (ex.HResult)
                {
                    default:
                        throw;
                }
            }
        }

我的方法:

static public SqlDataReader WeergevenRolPerUser(string userName)
            {
                try
                {
                    Open();
                    SqlCommand command = new SqlCommand("select * from [dbo].[fnShowDatabaseRole]('@UserName')", _connection);
                    command.Parameters.AddWithValue("@UserName", userName);
                    SqlDataReader myReader = command.ExecuteReader();
                    myReader.Read();
                    return myReader;
                }
                catch (Exception ex)
                {
                    switch (ex.HResult)
                    {
                        default:
                            throw;
                    }
                }
            }

Open() 方法:

private static void Open()
        {
            try
            {
                if (_connection.State != ConnectionState.Open)
                    _connection.Open();
            }
            catch (Exception ex)
            {
                switch (ex.HResult)
                {
                    default:
                        throw;
                }
            }
        }

这是我打电话给DataReader的地方:

 private void lstUsers_SelectedIndexChanged(object sender, EventArgs e)
        {
            SqlDataReader reader = null;
            try
            {
                if (_username != "" && lstUsers.SelectedValue != null)
                {
                    string user = lstUsers.SelectedValue.ToString();
                    reader = Database.Users.WeergevenRolPerUser(user);

                    if (reader.Read())
                    {
                        MessageBox.Show("unreachable");
                        var rol = reader.GetString(0);
                        if (rol == "gebruiker")
                        {
                            rdbUser.Checked = true;

                        }
                    }
                }
            }
            catch (Exception ex)
            {
                switch (ex.HResult)
                {
                    default:
                        throw;
                }
            }
            finally
            {
                if (reader != null) reader.Close();
            }


        }

【问题讨论】:

  • 信息不足。通常,您会使用 Profiler 来观察您的 sql 命令命中数据库,因此您确切地知道实际查询是什么(不是您假设的),然后您将其执行并在您的数据库以查看您实际返回的内容。这通常足以告诉你 90% 的时间发生了什么
  • 在数据库中执行查询是否返回结果?您可以在不引发任何异常的情况下调试应用程序吗?你也应该使用 using-Blocks。目前您没有关闭连接。
  • 拥有一个共享的Connection 对象通常是一个 的想法 - 共享连接string 但为每个@ 创建新的Connection 对象987654331@ 需要一个(并确保在使用后将它们包裹在 usingDispose 中)。
  • 没错,避免共享连接,甚至是读者。不要让您的数据层代码与 UI 代码混合,这是非常糟糕的做法。使您的代码难以阅读和理解。更不用说让连接打开的时间比需要的时间长、同步事件、管理状态的复杂性。数以万计的事情出错了!
  • 我真的不明白你们分享连接是什么意思。你建议我应该怎么做。我是编程的新手。你能给我举个例子正确的方法应该是什么?

标签: c# sqldatareader


【解决方案1】:

我的猜测是你在阅读器对象上调用了两次.Read(),根据MSDN

将 SqlDataReader 推进到下一条记录。

您在WeergevenRolPerUser 中执行此操作一次,它将读取您期望返回的数据,并在您发现的lstUsers_SelectedIndexChanged 中再次执行此操作,不会读取任何内容,因为没有下一条记录可以推进到。

如果我是你,我会更改 WeergevenRolPerUser 以返回 User 对象。

static public User WeergevenRolPerUser(string userName)
{
    try
    {
        using(var connection = new SqlConnection(/* connection string */))
        {
            connection.Open();

            using(var command = new SqlCommand("select * from [dbo].[fnShowDatabaseRole]('@UserName')", connection))
            {
                 command.Parameters.AddWithValue("@UserName", userName);

                 using(var myReader = command.ExecuteReader())
                 {
                     while(myReader.Read())
                     {
                         return new User
                                {
                                     Username = myReader.GetString(/* column index */),
                                     Role = myReader.GetString(/* column index */)
                                }
                     }
                 }

                 myReader.Close();
             }
         }
    catch (SqlException ex)
    {
        throw;
    }
}

【讨论】:

  • 似乎完全合理。我还要注意,OP 将列表视图事件与数据库代码混合并保持数据库连接打开的时间超过需要是非常糟糕的做法
  • 什么异常?请记住,您将使用所需的属性创建一个名为 User 的新类,并且您需要提供包含所需数据的列的正确索引。
  • "executereader 需要一个打开且可用的连接。连接的当前状态为关闭"
  • 啊,我的错,我错过了connection.Open(),然后将其传递给SqlCommand
  • 愚蠢的问题,但我需要把 connection.Open() 放在哪里?如果我把它放在 using 中,它会给我很多错误
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-03-22
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-08-02
相关资源
最近更新 更多