System.InvalidOperationException: 已有打开的与此 Command 相关联的 DataReader,必须首先将它关闭。

xietianci 2018-08-14 03:33:43
请大神帮我看看,怎么才能解决。

Protected Sub LoginButton_Click(sender As Object, e As EventArgs)
Dim Usernaem As String = Login1.UserName
Dim password As String = Login1.Password
Dim dates As String = System.DateTime.Now.ToString("yyyyMMdd")
Dim time As String = TimeOfDay
Dim count As Integer
cn = New SqlClient.SqlConnection(cnstr)
cn.Open()
Dim sqls As String = "select * from users where accounts='" & Usernaem.Trim & "' and password='" & password & "'"
cm = New SqlClient.SqlCommand(sqls, cn)
cm.CommandText = sqls
myreader = cm.ExecuteReader
myreader.Read()
cm.Connection = cn
count = cm.ExecuteScalar
Dim name As String = myreader("name")
myreader.Close()
If count > 0 Then
' Dim names As String = myreader.GetString(1).Trim
Dim sql As String = "insert into log (userid , name , 登录日期 , 登录时间 ) values('" & Usernaem & "','" & name & "','" & dates & "' , '" & time & "')"
da = New SqlClient.SqlDataAdapter(sql, cn)
ds = New DataSet(sql)
da.Fill(ds, "log")
If password = "123456@2018" Then
MsgBox("请先修改密码", vbSystemModal + MsgBoxStyle.OkOnly)
Server.Transfer("修改密码.aspx")
Else
Server.Transfer("webform1.aspx")

End If
Else
MsgBox("用户名或密码错误!")
End If
End Sub
End Class
...全文
875 5 打赏 收藏 转发到动态 举报
写回复
用AI写文章
5 条回复
切换为时间正序
请发表友善的回复…
发表回复
xietianci 2018-08-17
  • 打赏
  • 举报
回复
好的,我先学习学习
X-i-n 2018-08-15
  • 打赏
  • 举报
回复
感觉你是拿到代码就粘啊。粘之前先读一读啊。而且粘还粘错了。
拿到代码不先消化一下,直接就往上套,套100回你得问100回。
xietianci 2018-08-15
  • 打赏
  • 举报
回复

这里有错误提示,Name变量怎么定义,还有da.SelectCommand(sqls, cm) 这条也提示属性访问必须分配给属性或使用属性值
X-i-n 2018-08-14
  • 打赏
  • 举报
回复 1
你的问题发错版了,项目是.Net的。
总的看下来,感觉你对数据库操作这块一点概念都没有,对webform也没有了解过。
代码里问题有点多,数据库操作这块,建议重新找几个示例,仔细区分一下 SqlCommand获取数据的不同用法(Reader对象读取、SqlDataAdapter对象填充),也可以先简单参考一下我的Demo,里面涉及到了查询和插入;WEB这块,需要清楚地区分前端和后台,并且建议学习一下MVC,webform是已经淘汰了很多年的技术,如果是老项目已经在用WebForm,那就先随便找一本教材把WebForm过一遍,它和WinForm的语法没有区别,但是在命名空间、运行机制上区别很大。

Protected Sub LoginButton_Click(sender As Object, e As EventArgs)
Dim Usernaem As String = Login1.UserName
Dim password As String = Login1.Password
Dim dates As String = System.DateTime.Now.ToString("yyyyMMdd")
Dim time As String = TimeOfDay
Dim count As Integer
cn = New SqlClient.SqlConnection(cnstr)
cn.Open()
Dim sqls As String = "select * from users where accounts='" & Usernaem.Trim & "' and password='" & password & "'"

'sqlcommand可以重复使用:cm.CommandText="SQL语句";
'此句已经指定了cm的Connection为cn,下面那句cm.Connection = cn 是多余的;
'此句已经指定了cm的查询语句是 sqls,下面那句cm.CommandText = sqls 也是多余的。
cm = New SqlClient.SqlCommand(sqls, cn)

'这句是多余的,在定义cm的时候,已经指定了它的CommandText
cm.CommandText = sqls

myreader = cm.ExecuteReader
myreader.Read()

'这句是多余的,在定义cm的时候,已经指定了它的Connection
cm.Connection = cn

'count取不到值,按你的逻辑,用count来取记录条数,但是ExecuteScalar取到是查询结果里,第一条记录的第一个字段的值。
'count正确取值需要将sql改为 "SELECT COUNT(1) FROM ……",SQL执行结果是个integer,这才能按你的逻辑取到正确的值。
count = cm.ExecuteScalar

Dim name As String = myreader("name")
myreader.Close()
If count > 0 Then
' Dim names As String = myreader.GetString(1).Trim
Dim sql As String = "insert into log (userid , name , 登录日期 , 登录时间 ) values('" & Usernaem & "','" & name & "','" & dates & "' , '" & time & "')"
' SQLDATAADAPTER一般用来取数据,如果是执行一条sql,直接cm.CommandText="SQL语句", cm.ExecuteNonQuery(),后面这句返回一个integer,代表影响的sql条数
da = New SqlClient.SqlDataAdapter(sql, cn)
ds = New DataSet(sql)
da.Fill(ds, "log")
If password = "123456@2018" Then
'看你的代码是webform开发?webform里的msgbox没有意义,因为你写的所有代码都是在服务器上执
'行的,客户端根本看不到,正确的做法是生成前端js来alert报警消息
MsgBox("请先修改密码", vbSystemModal + MsgBoxStyle.OkOnly)
Server.Transfer("修改密码.aspx")
Else
Server.Transfer("webform1.aspx")
End If
Else
MsgBox("用户名或密码错误!")
End If
End Sub

Sub Demo()
Dim count As Integer
Dim cn As New SqlClient.SqlConnection(cnstr)
Dim cm As New SqlClient.SqlCommand(sqls, cn)
Dim da As New SqlClient.SqlDataAdapter()
Dim dt As New DataTable()

'你的sql有一个致命的问题,防不了注入,如果需要拼SQL,请使用参数化查询
'而且保存密码的时候,一般用Md5(如果更安全一点,可以用加盐的md5)来存储,不会明文存,
'否则被脱库的话,危害会非常大
Dim sqls As String = "select * from users where accounts='" & Usernaem.Trim & "' and password='" & password & "'"

cn.Open()

'执行SQL的时候
'要么用SqlDataReader读取(查)
'要么用ExecuteNonQuery()直接执行(增删改)
'要么用ExecuteScalar()直接取第一行第一列(查)
'要么用SqlDataAdapter去填充一个DataSet或者DataTable(查)
da.SelectCommand(cm)'为SqlDataAdapter绑定SqlCommand对象

'将SqlCommand的执行结果填充到数据表对象dt里,dt的Rows就是DataRow对象的集合,一个DataRow对象就是一条SQL记录;
'dt.Rows(i)可以取第i个DataRow对象,取到DataRow以后,用列名或者列序号可以取指定列的值。
da.Fill(dt)
If dt.Rows.Count>0 Then
cmd.CommandText = "insert into log (userid , name , 登录日期 , 登录时间 ) values('" & Usernaem & "','" & name & "','" & dates & "' , '" & time & "')";
Dim ret As Integer= cmd.ExecuteNonQuery() '这儿可以根据ret的结果来判断执行成功没有
'根据对应的user和pass能查到结果
If dt.Rows(0)("password")="123456@2018" Then
'需要修改密码
Else
'不需要修改密码,直接登录成功
End If
Else
'根据对应的user和pass查不到结果,结果集为空
End If
End Sub
End Class

1,216

社区成员

发帖
与我相关
我的任务
社区描述
VB 数据库(包含打印,安装,报表)
社区管理员
  • 数据库(包含打印,安装,报表)社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧