You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

VB.NET连接SQL Server启用MARS仍报连接已开错误如何解决?

问题根因(为什么启用MARS无效)

你遇到的报错和MARS的适用场景完全不匹配,启用MARS自然解决不了问题:

Cannot change property 'ConnectionString'. The current state of the connection is open

这个报错的本质是:你复用了全局的SqlConnection对象con,当它已经处于打开状态时,你的ConnServer()方法又尝试修改它的ConnectionString属性,这是被SQL Server连接类禁止的操作。MARS的作用是支持同一个打开的连接上同时存在多个活跃的DataReader结果集,完全不解决你当前的场景问题。

你的代码里还有几个直接导致报错的逻辑问题:

  • getemail方法里Return strMailTo 之后的sqLdr.Close()、closeCon() 代码永远不会执行,导致全局连接一直处于打开状态
  • 你在循环里每次调用getattachment都会再次执行ConnServer(),此时全局连接已经打开,修改ConnectionString直接触发报错
  • getemail里已经用SqlDataAdapter.Fill把数据加载到了DataTable,多余执行了一次cmd.ExecuteReader(),完全没有必要
  • 拼接SQL字符串存在SQL注入风险,属于额外的安全隐患

修复方案

核心原则

不要复用全局SqlConnection对象,.NET自带数据库连接池会自动管理连接的创建销毁,每次操作数据库时新建连接、用完自动释放即可。
所有实现了IDisposable接口的数据库操作对象(SqlConnection、SqlCommand、SqlDataAdapter、SqlDataReader)都用Using语句包裹,不需要手动调用Close/Dispose。

修正后的代码示例

可以完全弃用原来的ConnServer()和closeCon()全局连接管理方法,直接从配置读连接字符串每次新建连接:

' 先引入命名空间
Imports System.Data.SqlClient
Imports System.Configuration

Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
    Dim obj As String = TextBox1.Text
    Dim body As String = 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  "
    ' 每次新建连接,用Using自动释放
    Using con As New SqlConnection(ConfigurationManager.ConnectionStrings("ConString").ConnectionString)
        Using cmd As New SqlCommand(SQL, con)
            con.Open()
            Using sda As New SqlDataAdapter(cmd)
                Using ds As New DataTable()
                    sda.Fill(ds)
                    ' 不需要多余的ExecuteReader,直接遍历DataTable就行
                    For Each dr As DataRow In ds.Rows
                        strMailTo.Add(dr("EMail").ToString())
                    Next
                End Using
            End Using
        End Using
    End Using
    Return strMailTo
End Function

Function getattachment(email As String) As String()
    ' 参数化查询,避免SQL注入
    Dim SQL As String = "Select MatriculeSalarie  FROM [USER] WHERE [EMail]=@Email"
    Dim mat As String = ""
    Dim Dir As String = ConfigurationManager.AppSettings("path1").ToString()
    Using con As New SqlConnection(ConfigurationManager.ConnectionStrings("ConString").ConnectionString)
        Using cmd As New SqlCommand(SQL, con)
            ' 添加参数
            cmd.Parameters.AddWithValue("@Email", email)
            con.Open()
            Using sqLdr As SqlDataReader = cmd.ExecuteReader()
                While sqLdr.Read
                    mat = sqLdr.GetValue(sqLdr.GetOrdinal("MatriculeSalarie")).ToString()
                End While
            End Using
        End Using
    End Using
    Return IO.Directory.GetFiles(Dir, mat.Substring(1) & "*.pdf")
End Function

内容的提问来源于stack exchange,提问作者user9067306

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.03 19:18:01