用于 SQL Server 和 VB.NET 应用程序的 MultipleActiveResultSets
Posted
技术标签:
【中文标题】用于 SQL Server 和 VB.NET 应用程序的 MultipleActiveResultSets【英文标题】:MultipleActiveResultSets for SQL Server and VB.NET application 【发布时间】:2021-11-10 16:30:45 【问题描述】:我正在尝试使用 VB.NET 应用程序从 SQL Server 获取多个数据集。每次我尝试执行查询时的问题, 我收到这条消息:
无法更改属性“ConnectionString”。连接的当前状态是打开的
然后我尝试通过启用 MARS 来修复它
<connectionStrings>
<add name="ConString"
providerName="System.Data.SqlClient"
connectionString="Data Source=my-PC;Initial Catalog=Project;Persist Security Info=True; MultipleActiveResultSets=true;User ID=user;Password=*****" />
</connectionStrings>
这是我的代码
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
Dim obj, body
obj = TextBox1.Text
body = TextBox2.Text
For Each mail In getemail()
Send_mail(mail, obj, body, getattachment(mail))
Next
MsgBox("Traitement effectué")
End Sub
Function getemail() As List(Of String)
Dim strMailTo As New List(Of String)
Dim SQL As String = "Select EMail FROM [USER] WHERE EMail Is Not NULL And MatriculeSalarie Is Not NULL And [EMail] <> '' and EtatPaie = 3 and BulletinDematerialise = 1 "
Dim cmd As New SqlCommand
Dim sqLdr As SqlDataReader
Dim dr As DataRow
Try
ConnServer()
cmd.Connection = con
cmd.CommandText = SQL
Using sda As New SqlDataAdapter(cmd)
Using ds As New DataTable()
sda.Fill(ds)
sqLdr = cmd.ExecuteReader()
For i = 0 To ds.Rows.Count - 1
dr = ds.Rows(i)
strMailTo.Add(dr("EMail"))
Next
End Using
End Using
Return strMailTo
sqLdr.Close()
Catch ex As Exception
MsgBox(ex.Message.ToString)
End Try
closeCon()
Return strMailTo
End Function
Function getattachment(email) As String()
Dim SQL As String = "Select MatriculeSalarie FROM [USER] WHERE [EMail]='" & email & "'"
Dim cmd As New SqlCommand
Dim sqLdr As SqlDataReader
ConnServer()
cmd.Connection = con
cmd.CommandText = SQL
Dim mat As String
mat = ""
Dim Dir As String = ConfigurationManager.AppSettings("path1").ToString
Dim file()
sqLdr = cmd.ExecuteReader()
While sqLdr.Read
mat = sqLdr.GetValue(sqLdr.GetOrdinal("MatriculeSalarie"))
End While
file = IO.Directory.GetFiles(Dir, mat.Substring(1) & "*.pdf")
sqLdr.Close()
Return file
End Function
【问题讨论】:
对于这种特殊情况,您不需要 MARS。你做需要的是停止重用SqlConnection
对象。为每个查询创建一个新查询并在最后处理它(使用Using
语句),这就是它们的设计用途。每个SqlConnection
代表一个池连接的句柄,创建它们并不昂贵(超过第一个)。
请帮自己一个忙。如果不是更早,请立即阅读、理解并开始使用参数。您的代码对 sql 注入是开放的。
【参考方案1】:
如果您要做的只是在Catch
中显示一个消息框,请不要在数据库代码中这样做。让错误冒泡到用户界面代码,然后将Try
放在调用方法的位置。
不要声明没有 DataType 的变量。开启Option Infer的按钮代码设置obj
和body
的类型。
Private ConStr As String = "Your connection string"
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
Dim obj = TextBox1.Text
Dim body = TextBox2.Text
Dim emails As New List(Of String)
Try
emails = getemail()
Catch ex As Exception
MessageBox.Show(ex.Message.ToString, "Error retrieving email list")
Exit Sub
End Try
For Each email In emails
Try
Send_mail(email, obj, body, getattachment(email))
Catch ex As Exception
MessageBox.Show(ex.Message, "Error getting attachments")
End Try
Next
MessageBox.Show("Traitement effectué")
End Sub
Sub
和Function
使用的参数必须有一个DataType
。
我不知道你在这里做什么。
While sqLdr.Read
mat = sqLdr.GetValue(sqLdr.GetOrdinal("MatriculeSalarie"))
End While
每次迭代都会覆盖之前的 mat 值。我只能假设您只期望一个值,在这种情况下,您可以使用ExecuteScalar
来获取结果集第一行的第一列。在连接关闭之前不要对数据做任何事情。只需获取原始数据并关闭 (End Using
) 连接。稍后处理数据。
始终使用参数。数据库服务器不将参数视为可执行代码。它们只是价值观。可以插入的可执行代码示例是“Drop table [USER];”参数的值所属的位置。糟糕!
Function getemail() As List(Of String)
Dim SQL As String = "Select EMail FROM [USER]
WHERE EMail Is Not NULL
And MatriculeSalarie Is Not NULL
And [EMail] <> ''
And EtatPaie = 3
And BulletinDematerialise = 1;"
Dim dt As New DataTable
Using con As New SqlConnection("Your connection string"),
cmd As New SqlCommand(SQL, con)
con.Open()
Using reader = cmd.ExecuteReader
dt.Load(reader)
End Using
End Using
Dim strMailTo As New List(Of String)
strMailTo = (From row As DataRow In dt.AsEnumerable
Select row.Field(Of String)(0)).ToList
Return strMailTo
End Function
Function getattachment(email As String) As String()
Dim SQL As String = "Select MatriculeSalarie FROM [USER] WHERE [EMail]='" & email & "'"
Dim mat As String
Using con As New SqlConnection(ConStr),
cmd As New SqlCommand(SQL, con)
cmd.Parameters.Add("@email", SqlDbType.VarChar).Value = email
con.Open()
mat = cmd.ExecuteScalar().ToString()
End Using
Dim Dir As String = ConfigurationManager.AppSettings("path1").ToString
'Your original code was fine, no need for searchPattern.
'I added this so you could see if your search pattern was what you expected.
Dim searchPattern = mat.Substring(1) & "*.pdf"
Debug.Print(searchPattern) 'Appears in the Immediate window
Dim file = IO.Directory.GetFiles(Dir, searchPattern)
Return file
End Function
【讨论】:
以上是关于用于 SQL Server 和 VB.NET 应用程序的 MultipleActiveResultSets的主要内容,如果未能解决你的问题,请参考以下文章
如何使用 vb.net 和 SQL Server 裁剪和调整图像大小
SQL Server 中的存储过程未使用 VB.Net 编码填充 ASP.Net 下拉列表
使用 C#/VB.NET 实现 SQL Server Profiler
如何在其他 PC 上发布 VB.net 应用程序,因为我的 PC 成为使用 sql server 的服务器主机