В следующем коде, у меня есть выражение LINQ, который производит EnumerableRowCollection(Of DataRow)
, что, в конечном счете, используемый в BindingSource.
NewRow Datatable (в) метод вызывает повторную оценку выражения LINQ после того, как используется в качестве BindingSource с AsDataView()
При первом запуске кода все нормально. Однако после того, как для первого Control
был установлен с использованием AsDataView()
на IEnumerable
, при следующем вызове метода NewRow()
на DataTable
он повторно оценивает выражение LINQ.
Option Explicit On
Option Infer Off
Option Strict On
Public Class Form1
Dim ds As New DataSet()
Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
ds.Tables.Add("Table1")
Dim comparisonInteger As Integer = 12
ds.Tables("Table1").Columns.Add("ID", GetType(Integer))
ds.Tables("Table1").Columns.Add("IntegerValue", GetType(Integer))
ds.Tables("Table1").Columns.Add("StringValue", GetType(String))
ds.Tables("Table1").Rows.Add({1, 47, "row 1"})
ds.Tables("Table1").Rows.Add({2, 2, "row 1"})
ds.Tables("Table1").Rows.Add({3, 7, "row 1"})
ds.Tables("Table1").Rows.Add({4, 6, "row 1"})
For i As Integer = 0 To 2
Dim iterator As Integer = i
Dim tb As New TextBox()
CreateNewRowIfMissing(comparisonInteger+i)
Dim dataValue As EnumerableRowCollection(Of DataRow) = ds.Tables("Table1").AsEnumerable() _
.Where(Function(v) DirectCast(v("IntegerValue"), Integer) = comparisonInteger + iterator)
Dim bs As New BindingSource(dataValue.AsDataView(), Nothing)
Dim b As New Binding("Text", bs, "IntegerValue")
b.DataSourceUpdateMode = DataSourceUpdateMode.OnPropertyChanged
tb.DataBindings.Add(b)
tb.Location = New Point(10, 10 * Me.Controls.Count+1)
Me.Controls.Add(tb)
Next
End Sub
Private Sub CreateNewRowIfMissing(comparisonInteger As Integer)
If ds.Tables("Table1").AsEnumerable() _
.Where(Function(v) DirectCast(v("IntegerValue"), Integer) = comparisonInteger) _
.Count() = 0
ds.Tables("Table1").Rows.Add(ds.Tables("Table1").NewRow()) 'Prompts the dataValue IEnumerable to begin evaluating again.
ds.Tables("Table1").Rows(ds.Tables("Table1").Rows.Count-1)("ID") = ds.Tables("Table1").Rows.Count
ds.Tables("Table1").Rows(ds.Tables("Table1").Rows.Count-1)("IntegerValue") = comparisonInteger
ds.Tables("Table1").Rows(ds.Tables("Table1").Rows.Count-1)("StringValue") = "row" & ds.Tables("Table1").Rows.Count.ToString()
End If
End Sub
End Class
Чтобы уточнить, я имел обыкновение использовать стандартный DataView
с RowFilter
как BindingSource
, который работал:
Dim dv As New DataView(ds.Tables("Table1"))
dv.RowFilter = "IntegerValue=" & (comparisonInteger+iteratorValue)
Однако я чувствовал, что это могло бы быть лучше, чтобы использовать LINQ вместо.
Итак, что здесь происходит? Почему выражение LINQ основано на переоценке DataView
при вызове метода DataTable
NewRow()
? Есть ли способ предотвратить это?
Я надеялся, что AsDataView()
создал бы DataView
, который будет вести себя так же, как две вышеуказанные строки.
Как потенциал работы вокруг, я обнаружил, что я могу использовать это как BindingSource
«s DataSource
:
New DataView(dataValue.AsEnumerable().CopyToDataTable())
Однако, я обеспокоен потенциальной производительности с такой линии в будущее, и что я мог бы также использовать DataView
с RowFilter
, а не LINQ, если ему нужна вышеуказанная строка.
Ах, поэтому 'CopyToDataTable', безусловно, сломает мой DataBinding. Вероятно, должен был протестировать это, прежде чем рассматривать его как альтернативу. Во всяком случае, я понимаю, что он ссылается на одну и ту же таблицу (это то, что я хочу) в разделе «IEnumerable».Вы говорите, что когда в «DataTable» добавлена новая строка, это вызывает событие «ListChanged» в «DataView», что приводит к переоценке выражения linq, из которого был создан «DataView»? Насколько я понимаю это правильно? – Interminable
* 1) * Данные, полученные с помощью 'CopyToDataTable', содержат те же значения, но это еще одна ссылка. Это другой 'DataTable'. * 2) Событие 'ListChanged'' DataView' будет поднято при добавлении записи или внесении любых изменений в ее базовую 'DataTable'. * 3) * Событие 'ListChanged'' DataView' приводит к тому, что связанный контроль запрашивает данные, поэтому все данные, включая новые строки, возвращаются в 'DataGridView'. Например, если вы установили 'bs.RaiseListChangedEvents = false', вы не увидите изменений в' DataGridView'. –
Не беспокойтесь о производительности. Отображение новых записей, добавленных в DataTable, не оказывает негативного влияния на производительность. Просто подумайте о своем требовании и о том, что вам нужно. Затем, исходя из вашего требования, выберите решение. Например, если вам нужна привязка данных к исходным записям, вы должны использовать 'AsDataView'. Также, если вы не хотите показывать новые записи (я не знаю, почему), примените фильтр к 'DataView.RowFilter'. –