Imports System.Data.OleDb
Imports System.IO

Public Class Form1
    Inherits System.Windows.Forms.Form

#Region " Windows Form Designer generated code "

    Public Sub New()
        MyBase.New()

        'This call is required by the Windows Form Designer.
        InitializeComponent()

        'Add any initialization after the InitializeComponent() call

    End Sub

    'Form overrides dispose to clean up the component list.
    Protected Overloads Overrides Sub Dispose(ByVal disposing As Boolean)
        If disposing Then
            If Not (components Is Nothing) Then
                components.Dispose()
            End If
        End If
        MyBase.Dispose(disposing)
    End Sub

    'Required by the Windows Form Designer
    Private components As System.ComponentModel.IContainer

    'NOTE: The following procedure is required by the Windows Form Designer
    'It can be modified using the Windows Form Designer.  
    'Do not modify it using the code editor.
    Friend WithEvents C1SchemaDef1 As C1.Data.C1SchemaDef
    Friend WithEvents C1DataSet1 As C1.Data.C1DataSet
    Friend WithEvents ResyncDataSet As C1.Data.C1DataSet
    Friend WithEvents button3 As System.Windows.Forms.Button
    Friend WithEvents button2 As System.Windows.Forms.Button
    Friend WithEvents button1 As System.Windows.Forms.Button
    Friend WithEvents dataGrid1 As System.Windows.Forms.DataGrid
    <System.Diagnostics.DebuggerStepThrough()> Private Sub InitializeComponent()
        Dim resources As System.ComponentModel.ComponentResourceManager = New System.ComponentModel.ComponentResourceManager(GetType(Form1))
        Me.C1SchemaDef1 = New C1.Data.C1SchemaDef
        Me.C1DataSet1 = New C1.Data.C1DataSet
        Me.ResyncDataSet = New C1.Data.C1DataSet
        Me.button3 = New System.Windows.Forms.Button
        Me.button2 = New System.Windows.Forms.Button
        Me.button1 = New System.Windows.Forms.Button
        Me.dataGrid1 = New System.Windows.Forms.DataGrid
        CType(Me.C1SchemaDef1, System.ComponentModel.ISupportInitialize).BeginInit()
        CType(Me.C1DataSet1, System.ComponentModel.ISupportInitialize).BeginInit()
        CType(Me.ResyncDataSet, System.ComponentModel.ISupportInitialize).BeginInit()
        CType(Me.dataGrid1, System.ComponentModel.ISupportInitialize).BeginInit()
        Me.SuspendLayout()
        '
        'C1SchemaDef1
        '
        Me.C1SchemaDef1.DataObjectsAssemblyFlags = CType((C1.Data.DataObjectsAssemblyFlags.DataSetNamespaces Or C1.Data.DataObjectsAssemblyFlags.StaticNameFields), C1.Data.DataObjectsAssemblyFlags)
        Me.C1SchemaDef1.DummyImage = CType(resources.GetObject("C1SchemaDef1.DummyImage"), System.Drawing.Bitmap)
        Me.C1SchemaDef1.SerializedSchemaXML = Me.C1SchemaDef1.GetSchemaFromResources(resources, "C1SchemaDef1", Me)
        Me.C1SchemaDef1.SerializedDesignTimeOptionsXML = Me.C1SchemaDef1.GetDesignTimeOptionsFromResources(resources, "C1SchemaDef1", Me)
        '
        'C1DataSet1
        '
        Me.C1DataSet1.BindingContextCtrl = Me
        Me.C1DataSet1.DataLibrary = ""
        Me.C1DataSet1.DataLibraryUrl = ""
        Me.C1DataSet1.DataSetDef = "DataSet"
        Me.C1DataSet1.Locale = New System.Globalization.CultureInfo("en-US")
        Me.C1DataSet1.Name = "C1DataSet1"
        Me.C1DataSet1.SchemaClassName = ""
        Me.C1DataSet1.SchemaDef = Me.C1SchemaDef1
        '
        'ResyncDataSet
        '
        Me.ResyncDataSet.BindingContextCtrl = Me
        Me.ResyncDataSet.DataLibrary = ""
        Me.ResyncDataSet.DataLibraryUrl = ""
        Me.ResyncDataSet.DataSetDef = "DataSet"
        Me.ResyncDataSet.FillOnRequest = False
        Me.ResyncDataSet.Locale = New System.Globalization.CultureInfo("en-US")
        Me.ResyncDataSet.Name = "ResyncDataSet"
        Me.ResyncDataSet.SchemaClassName = ""
        Me.ResyncDataSet.SchemaDef = Me.C1SchemaDef1
        '
        'button3
        '
        Me.button3.Location = New System.Drawing.Point(440, 442)
        Me.button3.Name = "button3"
        Me.button3.Size = New System.Drawing.Size(136, 32)
        Me.button3.TabIndex = 7
        Me.button3.Text = "Resync all rows"
        '
        'button2
        '
        Me.button2.Location = New System.Drawing.Point(720, 442)
        Me.button2.Name = "button2"
        Me.button2.Size = New System.Drawing.Size(120, 32)
        Me.button2.TabIndex = 6
        Me.button2.Text = "Commit changes"
        '
        'button1
        '
        Me.button1.Location = New System.Drawing.Point(280, 442)
        Me.button1.Name = "button1"
        Me.button1.Size = New System.Drawing.Size(120, 32)
        Me.button1.TabIndex = 5
        Me.button1.Text = "Resync current row"
        '
        'dataGrid1
        '
        Me.dataGrid1.DataMember = "Customers"
        Me.dataGrid1.DataSource = Me.C1DataSet1
        Me.dataGrid1.HeaderForeColor = System.Drawing.SystemColors.ControlText
        Me.dataGrid1.Location = New System.Drawing.Point(40, 42)
        Me.dataGrid1.Name = "dataGrid1"
        Me.dataGrid1.Size = New System.Drawing.Size(808, 376)
        Me.dataGrid1.TabIndex = 4
        '
        'Form1
        '
        Me.AutoScaleBaseSize = New System.Drawing.Size(5, 13)
        Me.ClientSize = New System.Drawing.Size(888, 517)
        Me.Controls.Add(Me.button3)
        Me.Controls.Add(Me.button2)
        Me.Controls.Add(Me.button1)
        Me.Controls.Add(Me.dataGrid1)
        Me.Name = "Form1"
        Me.Text = "Form1"
        CType(Me.C1SchemaDef1, System.ComponentModel.ISupportInitialize).EndInit()
        CType(Me.C1DataSet1, System.ComponentModel.ISupportInitialize).EndInit()
        CType(Me.ResyncDataSet, System.ComponentModel.ISupportInitialize).EndInit()
        CType(Me.dataGrid1, System.ComponentModel.ISupportInitialize).EndInit()
        Me.ResumeLayout(False)

    End Sub

#End Region

    Private Sub ResyncRow(ByVal row As C1.Data.C1DataRow, ByVal dbRow As C1.Data.C1DataRow)
        ' This method synchronizes a simple table row with a row fetched from the database.
        If row.RowState <> C1.Data.DataRowStateEnum.Modified And row.RowState <> C1.Data.DataRowStateEnum.Unchanged Then
            ' deleted rows don't need synchronization; added rows don't exist in the database, so they also don't need synchronization
            Exit Sub
        End If
        Dim originalValuesChanged As Boolean = False ' this flag will be true if original values in the row should
        ' change as a result of the synchronization, i.e., the database row was changed by another user after the row was fetched
        Dim field As C1.Data.DataField
        For Each field In row.DataTable.Fields
            If Not row(field, C1.Data.DataRowVersionEnum.Original).Equals(dbRow(field.Name)) Then
                ' database value is different from the original value stored in the row
                ' (the database row was changed by another user after the row was fetched).
                originalValuesChanged = True
            End If
        Next field
        If originalValuesChanged Then
            row.BeginEdit()
            Dim changedValues As System.Collections.Specialized.ListDictionary = New System.Collections.Specialized.ListDictionary() ' we will save here all changes made to the row
            For Each field In row.DataTable.Fields
                If Not row(field).Equals(row(field.Name, C1.Data.DataRowVersionEnum.Original)) Then
                    ' value was changed, save the changes, to be applied after we call AcceptChanges.
                    changedValues.Add(field, row(field))
                End If
                ' Change the value in the row. It will become the new original value after we call AcceptChanges.
                row(field) = dbRow(field.Name)
            Next field
            ' Call AcceptChanges for the row. After this call, the current row values
            ' (which are copied from dbRow) become Original values of the row.
            ' This way we copied all field values from dbRow to row[, DataRowVersion.Original].
            row.AcceptChanges()
            ' Apply all the changes made by the current user to the row
            For Each field In changedValues.Keys
                row(field) = changedValues(field)
            Next field
            row.EndEdit()
        End If
    End Sub


    Private Sub button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles button1.Click
        ' Synchronize current row with the database.
        ' Changes made to this row by other users will appear in the row, unless the same field was
        ' changed by the current user.
        Dim cm As CurrencyManager = CType(BindingContext(C1DataSet1, "Customers"), CurrencyManager)
        If cm.Position < 0 Then
            MessageBox.Show("No current row")
            Exit Sub
        End If
        ' Get the current row
        Dim tableViewRow As C1.Data.C1DataRow = C1.Data.C1DataRow.FromDataItem(cm.Current)
        Dim customerID As String = tableViewRow("CustomerID").ToString()
        Dim dataTable As C1.Data.C1DataTable = C1DataSet1.Tables("Customers")
        Dim tableRow As C1.Data.C1DataRow = dataTable.Rows.Find(customerID)
        ' Fetch the row from the database to the temporary data set resyncDataSet, using the primary key, CustomerID value as filter.
        ' This will fill resyncDataSet with a single row (or no rows, if the row was deleted by another user)
        Dim filter As C1.Data.FilterCondition = New C1.Data.FilterCondition(ResyncDataSet, "Customers", "[CustomerID] = '" + customerID + "'")
        ResyncDataSet.Fill(filter, False)
        Dim resyncDataTable As C1.Data.C1DataTable = ResyncDataSet.Tables("Customers")
        If resyncDataTable.Rows.Count = 0 Then
            ' Row was deleted from the database by another user
            MessageBox.Show("Row with CustomerID=" + customerID + " no longer exists in the database")
            Exit Sub
        End If
        ' Synchronize the row
        Dim dbRow As C1.Data.C1DataRow = resyncDataTable.Rows(0)
        ResyncRow(tableRow, dbRow)
    End Sub

    Private Sub button3_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles button3.Click
        ' Synchronize all rows with the database.
        ' Changes made by other users will become visible in our rowset.
        ' Changes made by the current user are preserved.
        ' Rows added by other users will appear, rows deleted by other users will disappear
        ' (unless they were changed by the current user), rows modified by other users
        ' will show new field values (except fields changed by the current user, all changes
        ' made by the current user are preserved).
        '
        ' Fetch data from the database to the temporary data set resyncDataSet
        ResyncDataSet.Fill()
        ' Get the changes made by the current user. We use the ADO.NET GetChanges method to get the changes.
        Dim changesAddedDeleted As System.Data.DataSet = C1DataSet1.StorageDataSet.GetChanges(System.Data.DataRowState.Added + System.Data.DataRowState.Deleted)
        Dim changesModified As System.Data.DataSet = C1DataSet1.StorageDataSet.GetChanges(System.Data.DataRowState.Modified)
        ' To modify the ADO.NET data table storing C1DataTable's data, we need to
        ' use StorageChangeBegin/StorageChanged/StorageChangeEnd
        ' (see "Working with ADO.NET Dataset" in C1DataObjects documentation)
        C1DataSet1.StorageChangeBegin()
        Dim customersTable As C1.Data.C1DataTable = C1DataSet1.Tables("Customers")
        ' Using ADO.NET method Merge, copy data fetched from the database to our Customers table
        customersTable.StorageDataTable.Clear()
        C1DataSet1.StorageDataSet.Merge(ResyncDataSet.Tables("Customers").StorageDataTable)
        ' Now the Customers table is filled with rows that are currently in the database
        customersTable.StorageDataTable.AcceptChanges()
        ' If there are changes made by the current user, apply those changes to the Customers table.
        If Not (changesAddedDeleted Is Nothing) Then
            ' To apply added and deleted rows, we use the ADO.NET Merge method
            Dim changesCustomers As System.Data.DataTable = changesAddedDeleted.Tables("Customers")
            If Not (changesCustomers Is Nothing) Then
                C1DataSet1.StorageDataSet.Merge(changesCustomers)
            End If
        End If
        If Not (changesModified Is Nothing) Then
            ' To apply modified rows, we go row-by-row and change field values
            Dim changesCustomers As System.Data.DataTable = changesModified.Tables("Customers")
            If Not (changesCustomers Is Nothing) Then
                Dim modifiedRow As System.Data.DataRow
                For Each modifiedRow In changesCustomers.Rows
                    Dim dataRow As System.Data.DataRow = customersTable.StorageDataTable.Rows.Find(modifiedRow("CustomerID"))
                    If Not (dataRow Is Nothing) Then
                        Dim column As System.Data.DataColumn
                        For Each column In modifiedRow.Table.Columns
                            If Not modifiedRow(column).Equals(modifiedRow(column, System.Data.DataRowVersion.Original)) Then
                                dataRow(column.ColumnName) = modifiedRow(column)
                            End If
                        Next column
                    End If
                Next modifiedRow
            End If
        End If
        ' Table Customers is synchronized with the database.
        C1DataSet1.StorageChanged(True)
        ' In this sample, we do nothing between StorageChanged and StorageChangeEnd, thus allowing C1DataObjects
        ' to fill all table views (we have only one table view in this sample) with table rows.
        ' If your table views are restricted (if you used FilterConditions filling the data set),
        ' you may need to call SetTableViewRows here, see "Working with ADO.NET Dataset" in C1DataObjects documentation.
        C1DataSet1.StorageChangeEnd()
    End Sub

    Private Sub button2_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles button2.Click
        ' Commit changes to the database
        C1DataSet1.Update()
    End Sub

#Region " Switch to C1NWind.mdb database "

    Private Sub C1SchemaDef1_CreateSchema(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles C1SchemaDef1.CreateSchema
        Dim dbPath As String = Environment.GetFolderPath(Environment.SpecialFolder.Personal) + _
            "\ComponentOne Samples\Common\C1NWind.mdb"
        If File.Exists(dbPath) Then
            Dim conn As C1.Data.SchemaObjects.Connection = C1SchemaDef1.Schema.Connections(0)
            Dim csb As New OleDbConnectionStringBuilder(conn.ConnectionString)
            csb.DataSource = dbPath
            conn.ConnectionString = csb.ToString()
        End If
    End Sub

#End Region

End Class
