Почему этот код не обновляет таблицу базы данных?
В устаревшем приложении ASP.NET Webforms мне нужно обновить таблицу базы данных, когда пользователь нажимает кнопку, в зависимости от того, какие флажки в форме установлены, используя значение из соответствующей метки для обновления.
Это не работает; однако почти идентичный код в "тестовом" приложении Winforms работает.
Код FormLoad (Winforms) и Page_Load (Webforms) работает нормально; нет необходимости показывать весь этот код; они оба заполняют форму / страницу парами элементов управления метка / флажок.
Однако, чтобы показать, как они отличаются друг от друга: Когда элементы управления создаются динамически, они присваивают строковое значение тега (Winforms) или ID (Webforms) (подробнее об этом ниже).
В рабочем (Winforms) коде это делается так:
Dim lblCompanyName = New Label()
lblCompanyName.Tag = i.ToString()
lblCompanyName.Text = reader.Item(0).ToString()
Me.Controls.Add(lblCompanyName)
Dim ckbx = New CheckBox()
ckbx.Tag = i.ToString()
ckbx.Checked = True
Me.Controls.Add(ckbx)
В нерабочем коде (Webforms) это делается следующим образом:
Dim coName = New Label()
' Must prepend with something, as controls cannot share the same ID
coName.ID = "lbl" + i.ToString()
coName.Text = categoryDT.Rows(i)(0).ToString()
formCustCatMaint.Controls.Add(coName)
Dim chk = New CheckBox()
chk.ID = "ckbx" + i.ToString()
chk.Checked = True
formCustCatMaint.Controls.Add(chk)
Помимо кода загрузки формы / страницы, есть только три других блока кода: обработчик события нажатия кнопки и два служебных метода, вызываемых этим обработчиком.
Работает код в приложении Winforms, который использует.NET Framework 4.5 (обновляет таблицу базы данных при нажатии кнопки); код в приложении Webforms, который использует.NET Framework 2, не обновляет таблицу базы данных так, как должно - но пока не показывает страницы ошибок, просто сладко ухмыляется и лениво почивает на лаврах.
Единственное реальное различие, которое я вижу в коде между ними, заключается в том, что в одном случае (приложение Winforms) свойству Tag динамически созданным элементам управления присваивается значение, тогда как в другом (сайт Webforms) динамически создаваемые элементы управления ' ID свойство это то, что назначено. Кстати, ни одна из технологий, похоже, не имеет другого доступного свойства (кажется, что Winforms не могут получить доступ к свойству ID для элемента управления, а Webforms не может получить доступ к свойству Tag для элемента управления).
Отличие заключается в том, что никакие два элемента управления не могут иметь одинаковый идентификатор (веб-формы); таким образом, я должен добавить "lbl" к идентификаторам элементов управления Label и "ckbx" к идентификаторам элементов управления Checkbox (каждая пара имеет одно и то же число, так что "lbl1" и "ckbx1" - это согласованная пара, "lbl42" и "ckbx42"- согласованная пара и т. д.).
Почему почти идентичный код в приложении Webforms не может обновить базу данных?
Вот рабочий код (Winforms/.NET 4.5) для этих трех блоков кода:
Private Sub Button1_Click( sender As Object, e As EventArgs) Handles Button1.Click
Dim connStr As String = "SERVER=PLATYPUS42;DATABASE=duckbilldata;UID=schnozz;PWD=pondscum"
Dim upd8DML As String = "UPDATE CustomerCategoryLog SET Category = 'Exploding' WHERE Unit = @Unit And MemberNo = @MemberNo AND Custno = @CustNo"
Dim coName As String
Dim argVals(2) As String
Dim _Unit As String
Dim _MemberNo As String
Dim _CustNo As String
Dim curTagVal As String
For Each cntrl As Control In Me.Controls
If TypeOf cntrl Is CheckBox Then
If DirectCast(cntrl, CheckBox).Checked = True Then
curTagVal = CStr(DirectCast(cntrl, CheckBox).Tag)
coName = GetLabelTextForTag(curTagVal)
argVals = GetArgValsForCompanyName(coName)
_Unit = argVals(0)
_MemberNo = argVals(1)
_CustNo = argVals(2)
Using conn As New SqlConnection(connStr), _
cmd As New SqlCommand(upd8DML, conn)
cmd.Parameters.Add("@Unit", SqlDbType.VarChar, 50).Value = _Unit
cmd.Parameters.Add("@MemberNo", SqlDbType.VarChar, 50).Value = _MemberNo
cmd.Parameters.Add("@CustNo", SqlDbType.VarChar, 50).Value = _CustNo
conn.Open
cmd.ExecuteScalar()
End Using
End If
End If
Next
End Sub
Protected Function GetLabelTextForTag(tagVal As String) As String
Dim CoName As String = ""
For Each cntrl As Control In Me.Controls
If TypeOf cntrl Is Label Then
If DirectCast(cntrl, Label).Tag.ToString() = tagVal Then
CoName = DirectCast(cntrl, Label).Text
Exit For
End If
End If
Next
Return CoName
End Function
Protected Function GetArgValsForCompanyName(coName As String) As String()
Dim args(2) As String
Using con As New SqlConnection("SERVER=PLATYPUS42;DATABASE=duckbilldata;UID=schnozz;PWD=pondscum"),
cmd As New SqlCommand("select Unit, MemberNo, CustNo from Customers WHERE CompanyName = @CoName", con)
con.Open()
cmd.CommandType = CommandType.Text
cmd.Parameters.Add("@CoName", SqlDbType.VarChar, 50).Value = coName
Using reader As SqlDataReader = cmd.ExecuteReader
While reader.Read
args(0) = reader.Item(0).ToString()
args(1) = reader.Item(1).ToString()
args(2) = reader.Item(2).ToString()
End While
End Using
End Using
Return args
End Function
... и вот код нерабочего (Webforms/.NET 2.0) для соответствующих блоков кода:
Protected Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
Dim connStr As String = "SERVER=PLATYPUS42;DATABASE=duckbilldata;UID=schnozz;PWD=pondscum"
Dim upd8DML As String = "UPDATE CustomerCategoryLog SET Category = 'Exploding' WHERE Unit = @Unit And MemberNo = @MemberNo AND Custno = @CustNo"
Dim coName As String
Dim argVals(2) As String
Dim _Unit As String
Dim _MemberNo As String
Dim _CustNo As String
Dim curCheckboxIDVal As String
For Each cntrl As Control In Me.Controls
If TypeOf cntrl Is CheckBox Then
If DirectCast(cntrl, CheckBox).Checked = True Then
curCheckboxIDVal = CStr(DirectCast(cntrl, CheckBox).ID)
coName = GetLabelTextForID(curCheckboxIDVal)
argVals = GetArgValsForCompanyName(coName)
_Unit = argVals(0)
_MemberNo = argVals(1)
_CustNo = argVals(2)
Using conn As New SqlConnection(connStr), _
cmd As New SqlCommand(upd8DML, conn)
cmd.Parameters.Add("@Unit", SqlDbType.VarChar, 50).Value = _Unit
cmd.Parameters.Add("@MemberNo", SqlDbType.VarChar, 50).Value = _MemberNo
cmd.Parameters.Add("@CustNo", SqlDbType.VarChar, 50).Value = _CustNo
conn.Open
cmd.ExecuteScalar()
End Using
End If
End If
Next
End Sub
Protected Function GetLabelTextForID(ckbxIDVal As String) As String
Dim CoName As String = ""
Dim _idVal As String = ckbxIDVal
Dim numberLen As Integer = _idVal.Length - "ckbx".Length
_idVal = _idVal.Substring("ckbx".Length, numberLen)
LabelDebug.Text = _idVal
For Each cntrl As Control In Me.Controls
If TypeOf cntrl Is Label Then
If DirectCast(cntrl, Label).ID = "lbl" + _idVal Then
CoName = DirectCast(cntrl, Label).Text
Exit For
End If
End If
Next
Return CoName
End Function
Protected Function GetArgValsForCompanyName(coName As String) As String()
Dim args(2) As String
Using con As New SqlConnection("SERVER=PLATYPUS42;DATABASE=duckbilldata;UID=schnozz;PWD=pondscum"), _
cmd As New SqlCommand("select Unit, MemberNo, CustNo from Customers WHERE CompanyName = @CoName", con)
con.Open()
cmd.CommandType = CommandType.Text
cmd.Parameters.Add("@CoName", SqlDbType.VarChar, 50).Value = coName
Using reader As SqlDataReader = cmd.ExecuteReader
While reader.Read
args(0) = reader.Item(0).ToString()
args(1) = reader.Item(1).ToString()
args(2) = reader.Item(2).ToString()
End While
End Using
End Using
Return args
End Function
Как видите, код практически идентичен, но результаты (успех / неудача) диаметрально противоположны. Зачем?
ОБНОВИТЬ
Видимо эта строка не работает:
If TypeOf cntrl Is CheckBox Then
Хотя на странице есть флажки, этот тест не пройден. Зачем?
Я знаю это, потому что я добавил несколько "отладочных" тестов в обработчик Button1_Click, например, так (не могу пройти по коду):
For Each cntrl As Control In Me.Controls
Label2.Text="label 2 text from foreach"
If TypeOf cntrl Is CheckBox Then
Label2.Text="label 2 text from is checkbox"
If DirectCast(cntrl, CheckBox).Checked = True Then
Label2.Text="label 2 text from checked"
. . .
Последний текст, написанный в Label2, - это "текст метки 2 от foreach".
Таким образом, "Если TypeOf cntrl Is CheckBox Затем" не удается.
Чекбоксы не видны, потому что они были созданы динамически? Если так, как я могу обойти это?
ОБНОВЛЕНИЕ 2
Когда я добавляю это в соответствующий файл.aspx:
<%@ Page Language="VB" AutoEventWireup="true" IsPostback="true" CodeFile="custmaint_categoryadmin.aspx.vb"
Inherits="pages_custmaint_categoryadmin" %>
(добавлена часть "IsPostback="true"")
... "IsPostback" подчеркивается красными волнистыми попугайчиками, и когда я запускаю его, я получаю:
Parser Error
Description: An error occurred during the parsing of a resource required to service this request. Please review the following specific parse error details and modify your source file appropriately.
Parser Error Message: Error parsing attribute 'ispostback': The 'ispostback' property is read-only and cannot be set.
Source Error:
Line 1: <%@ Page Language="VB" AutoEventWireup="true" IsPostback="true" CodeFile="custmaint_categoryadmin.aspx.vb" Inherits="pages_custmaint_categoryadmin" %>
Line 2:
Line 3: <!DOCTYPE html>
ОБНОВЛЕНИЕ 3
Теперь мне кажется, что здесь есть нечто сверхъестественное: я поставил флажок на веб-форме и снова запустил ее. Даже если в форме установлен флажок "видимый во время разработки", он все равно не пройдет тест "If TypeOf cntrl Is CheckBox Then"; последнее обновление Label2.Text по-прежнему "текст метки 2 от foreach"
Как может случиться, что флажок, особенно "конкретный", а не динамический, не приравнивается к флажку?!?