#vb.net #ms-access #oledb
#vb.net #ms-access #oledb
Вопрос:
Я застрял с этой проблемой весь день, так что, возможно, у кого-то есть совет для меня.
Среда: MS Access DB, VB.NET , OleDb-драйвер, MS Access Database Engine 2016.
Я пытаюсь привязать поле Long / Int64 к элементу управления NumericUpDown, но при обновлении я всегда получаю исключение OleDbException «Слишком мало параметров». Я почти уверен, что проблема в длинном поле, потому что, когда я удаляю его из таблицы (и закомментирую код для него), все работает нормально. Я не уверен, что NumericUpDown подходит для этой задачи, но его базовый тип данных — decimal, а decimal имеет гораздо больше места, чем нужно для long . Итак, вот некоторый код:
В dataLayer:
Private Sub InitializeDataSet()
Dim LocFields = String.Join("], [", Fields)
Dim SQL As String = "SELECT [" amp; LocFields amp; "] FROM [" amp; Table amp; "]"
DAMain = New OleDbDataAdapter(SQL, Connection)
Using Builder As New OleDbCommandBuilder(DAMain) With {
.ConflictOption = ConflictOption.OverwriteChanges
}
Builder.GetInsertCommand()
Builder.GetUpdateCommand()
Builder.GetDeleteCommand()
End Using
DS = New DataSet
DAMain.Fill(DS, Table)
End Sub
Public Sub Update()
DAMain.Update(DS, Table) ' <-- Here the exception happens
End Sub
Public ReadOnly Property DataSource As Object
Get
Return DS
End Get
End Property
Public ReadOnly Property DataMember As String
Get
Return Table
End Get
End Property
Мы здесь в классе, поэтому переменные:
Таблица = имя таблицы
Поля = список полей в таблице
Соединение = OleDbConnection
DAMain = OleDbDataAdapter
DS = набор данных
В форме:
Private DL As OleDbDataLayer
Private WithEvents BSource As New BindingSource
Public Sub New(DataLayer As OleDbDataLayer)
InitializeComponent()
DL = DataLayer
BSource.DataSource = DL.DataSource
BSource.DataMember = DL.DataMember
BSource.AllowNew = True
BSource.Sort = DL.OrderBy
BSource.Position = 0
InitializeFields()
End Sub
Private Sub DataUpdate()
BSource.EndEdit()
DL.Update()
End Sub
Private Sub InitializeFields()
NUD.Minimum = Long.MinValue
NUD.Maximum = Long.MaxValue
Dim Binding As New Binding("Value", BSource, "F_Long")
AddHandler Binding.Format, AddressOf FormatDBNull
AddHandler Binding.Parse, AddressOf ParseNumericUpDown
NUD.DataBindings.Add(Binding)
End Sub
Private Sub FormatDBNull(sender As Object, e As ConvertEventArgs)
If Convert.IsDBNull(e.Value) Then
Select Case e.DesiredType
Case = GetType(Decimal) : e.Value = 0
Case = GetType(Date) : e.Value = Today
Case = GetType(Boolean) : e.Value = False
Case Else
End Select
End If
End Sub
Private Sub ParseNumericUpDown(sender As Object, e As ConvertEventArgs)
Select Case e.DesiredType
Case = GetType(Byte)
e.Value = Convert.ToByte(e.Value)
Case = GetType(Short)
e.Value = Convert.ToInt16(e.Value)
Case = GetType(Integer)
e.Value = Convert.ToInt32(e.Value)
Case = GetType(Long)
e.Value = Convert.ToInt64(e.Value)
Case Else
' Do Nothing
End Select
End Sub
Здесь NUD — это элемент управления NumericUpDown, который должен быть очевидным.
Может быть, мне следует использовать другой тип элемента управления? Текстовое поле? MaskedTextBox?
Комментарии:
1. Вы уверены, что DS и Table не равны нулю при попытке обновления?
2. ДА. Я только что протестировал его. Но я был совершенно уверен, потому что, как я уже сказал, код работает нормально, если в таблице нет длинного поля.
3. Я не знаю, может ли это иметь какое-либо отношение к проблеме, но
NumericUpDown.Value
это десятичное число.4. @Mary: Да, я знаю. Но десятичное число .NET состоит из 16 байт / 128 бит. Этого должно быть достаточно для хранения 8-байтового / 64-битного числа. Другой аргумент: между тем у меня была точно такая же проблема с другим элементом управления, измененным текстовым полем. Я думаю, проблема в том, что 64-битная длина является совершенно новой в Access .