Đây là một câu hỏi khái niệm hơn. Đây là tình trạng khó khăn hiện tại của tôi; Tôi đang viết một ứng dụng WPF vb.net và sử dụng mẫu MVVM (yêu nó! Khả năng bảo trì chỉ là tuyệt vời). Hiện tại tất cả các mã được viết bằng tay và không sử dụng NHibernate hoặc Entity Framework vì backend là cơ sở dữ liệu truy cập (do chính sách tôi không thể sử dụng NH và EF không hỗ trợ Cơ sở dữ liệu JET, chúng tôi có thể chuyển sang MSSQL tại một số điểm nhưng đó có thể là một lúc kể từ bây giờ).Cách thích hợp để cập nhật các bản ghi trong mẫu MVVM cho hiệu quả tối đa
Ứng dụng đang chạy khá tốt và tự hỏi cách tốt nhất để gửi cập nhật về cơ sở dữ liệu là gì.
Hiện tại, phương pháp là thêm boolean vào bản ghi trên phần thiết lập của mô hình thành "dirty", khi cập nhật được nhấn, chúng tôi lặp qua tất cả các bản ghi "bẩn" và sử dụng oledbcommand (thực thi với tham số) câu lệnh sql để cập nhật. Điều này tạo ra một sự tách biệt tuyệt vời của mối quan tâm nhưng nếu đây là sai cách tôi muốn biết lựa chọn thay thế (xin lưu ý các loại cơ sở dữ liệu và các hạn chế liên quan như vậy là nó không làm việc với EF).
Cảm ơn!
mã cuối cùng trong VB.NET sau ý kiến vv:
Public Class Car
Implements ICloneable
Public Property Make() As String
Get
Return m_Make
End Get
Set(ByVal value As String)
m_Make = value
End Set
End Property
Private m_Make As String
Public Property Model() As String
Get
Return m_Model
End Get
Set(ByVal value As String)
m_Model = value
End Set
End Property
Private m_Model As String
Public Function Clone() As Object Implements System.ICloneable.Clone
Return New Car() With { _
.Make = Me.Make, _
.Model = Me.Model _
}
End Function
End Class
Public Class CarEqualityComparer
Implements IEqualityComparer(Of Car)
Public Overloads Function Equals(ByVal x As Car, ByVal y As Car) As Boolean Implements System.Collections.Generic.IEqualityComparer(Of Car).Equals
Return x.Make = y.Make AndAlso x.Model = y.Model
End Function
Public Overloads Function GetHashCode(ByVal obj As Car) As Integer Implements System.Collections.Generic.IEqualityComparer(Of Car).GetHashCode
Return 1 'http://blogs.msdn.com/b/jaredpar/archive/2008/06/03/making-equality-easier.aspx
End Function
End Class
Public Class CarRepository
Private _carComparator As New CarEqualityComparer
Private _cars As New ChangeTracker(Of Car)(_carComparator)
Public Function GetCars() As IEnumerable(Of Car)
'TODO: JET/ADO code here, you would obviously do in a for/while loop
Dim dbId1 As Integer = 1
Dim make1 As String = "Ford"
Dim model1 As String = "Focus"
Dim dbId2 As Integer = 2
Dim make2 As String = "Hyundai"
Dim model2 As String = "Elantra"
'TODO: create or update car objects
Dim car1 As Car
If Not _cars.IsTracking(dbId1) Then
car1 = New Car()
Else
car1 = _cars.GetItem(dbId1)
End If
car1.Make = make1
car1.Model = model1
If Not _cars.IsTracking(dbId1) Then
_cars.StartTracking(dbId1, car1)
End If
Dim car2 As Car
If Not _cars.IsTracking(dbId2) Then
car2 = New Car()
Else
car2 = _cars.GetItem(dbId2)
End If
car2.Make = make2
car2.Model = model2
If Not _cars.IsTracking(dbId2) Then
_cars.StartTracking(dbId2, car2)
End If
Return _cars.GetTrackedItems()
End Function
Public Sub SaveCars(ByVal cars As IEnumerable(Of Car))
'TODO: JET/ADO code here to update the item
Console.WriteLine("Distinct " & cars.Distinct.Count.ToString)
For Each changedItem As Car In _cars.GetChangedItems().Intersect(cars)
Console.Write("Saving: ")
Console.WriteLine(changedItem.Make)
Next
For Each newItem As Car In cars.Except(_cars.GetTrackedItems())
Console.Write("Adding: ")
Console.WriteLine(newItem.Make)
Dim newId As Integer = CInt(Math.Ceiling(Rnd() * 5000)) 'Random right now but JET/ADO to get the id later....
_cars.StartTracking(newId, newItem)
Next
Dim removalArray As New ArrayList
For Each deletedItem As Car In _cars.GetTrackedItems().Except(cars)
Console.Write("Removing: ")
Console.WriteLine(deletedItem.Make)
removalArray.Add(_cars.GetId(deletedItem)) 'Cannot remove right as iterating through array - clearly that would be problematic....
Next
For Each dbId As Integer In removalArray
_cars.StopTracking(dbId)
Next
_cars.SetNewCheckpoint()
End Sub
End Class
Public Class ChangeTracker(Of T As {ICloneable})
'item "checkpoints" that are internal to this list
Private _originals As New Dictionary(Of Integer, T)()
Private _originalIndex As New Dictionary(Of T, Integer)()
'the current, live-edited objects
Private _copies As New Dictionary(Of Integer, T)()
Private _copyIndex As New Dictionary(Of T, Integer)()
Private _comparator As System.Collections.Generic.IEqualityComparer(Of T)
Public Sub New(ByVal comparator As System.Collections.Generic.IEqualityComparer(Of T))
_comparator = comparator
End Sub
Public Function IsChanged(ByVal copy As T) As Boolean
Dim original = _originals(_copyIndex(copy))
Return Not _comparator.Equals(copy, original)
End Function
Public Function GetChangedItems() As IEnumerable(Of T)
Dim items As IEnumerable(Of T)
items = _copies.Values.Where(Function(c) IsChanged(c))
Return items
End Function
Public Function GetTrackedItems() As IEnumerable(Of T)
Return _copies.Values
End Function
Public Sub SetNewCheckpoint()
For Each copy In Me.GetChangedItems().ToList()
Dim dbId As Integer = _copyIndex(copy)
Dim oldOriginal = _originals(dbId)
Dim newOriginal = DirectCast(copy.Clone(), T)
_originals(dbId) = newOriginal
_originalIndex.Remove(oldOriginal)
_originalIndex.Add(newOriginal, dbId)
Next
End Sub
Public Sub StartTracking(ByVal dbId As Integer, ByVal item As T)
Dim newOriginal = DirectCast(item.Clone(), T)
_originals(dbId) = newOriginal
_originalIndex(newOriginal) = dbId
_copies(dbId) = item
_copyIndex(item) = dbId
End Sub
Public Sub StopTracking(ByVal dbId As Integer)
Dim original = _originals(dbId)
Dim copy = _copies(dbId)
_copies.Remove(dbId)
_originals.Remove(dbId)
_copyIndex.Remove(copy)
_originalIndex.Remove(original)
End Sub
Public Function IsTracking(ByVal dbId As Integer) As Boolean
Return _originals.ContainsKey(dbId)
End Function
Public Function IsTracking(ByVal item As T) As Boolean
Return _copyIndex.ContainsKey(item)
End Function
Public Function GetItem(ByVal dbId As Integer) As T
Return _copies(dbId)
End Function
Public Function GetId(ByVal item As T) As Integer
Dim dbId As Integer = (_copyIndex(item))
Return dbId
End Function
End Class
Xin chào Kevin, tôi chỉ hiểu một nửa điều này - bạn có thể giải thích điều gì đang thực sự xảy ra trong mã đó không? Loại giống như một câu chuyện? –
Xin chào Omar, tôi đã thực hiện một vài chỉnh sửa, tôi hy vọng điều đó sẽ hữu ích. Các phiên bản rất ngắn là chúng tôi vẫn đang làm theo dõi bẩn, ngoại trừ chúng tôi chỉ tính toán đối tượng nào bị bẩn khi người dùng nhấp vào Lưu, thay vì quản lý cờ bẩn khi người dùng thực hiện thay đổi. –
Xin chào Kevin, Còn về GetHashCode trong buồng trứng thì sao? –