Back to Devexpress

Post Data to an Underlying Data Source

windowsforms-1082-controls-and-libraries-data-grid-data-binding-post-data-to-an-underlying-data-source.md

latest20.0 KB
Original Source

Post Data to an Underlying Data Source

  • Sep 20, 2024
  • 9 minutes to read

Common Tips

Data Grid (like other DevExpress data-aware controls) works with a data source that retrieves data from a database. The grid does not interact with an underlying database directly. To push changes to an underlying database, use your data source’s API.

Handle the following events to post changes to the database (regardless of the data binding method):

|

Event

|

Description

| | --- | --- | |

ColumnView.RowUpdated

|

Occurs after a user modifies a row and tries to navigate to another row. RowUpdated does not fire while the editor is still active. To push changes, you need to close the editor first (BaseView.CloseEditor) and call the BaseView.UpdateCurrentRow method to trigger this event manually.

| |

ColumnView.InitNewRow

|

Occurs when a user adds a data row.

| |

ColumnView.RowDeleted

|

Occurs when a user deletes a data row.

| |

Form.Closing

|

A standard WinForms event that allows you to avoid excessive updates and save all changes at once before closing the application.

|

Master-Detail Specifics

In master-detail mode, Views that you assign to detail levels are Pattern Views. The Data Grid dynamically creates a Clone View based on settings of its pattern view when a user expands a master row (a clone view is a copy of a pattern view). To post changes made in Clone Views to the grid’s data source, do the following:

  1. Use the GridView.GetDetailView method to get a Clone View.

  2. Call the Clone View’s CloseEditor and UpdateCurrentRow methods.

Read the following help topic for more information: Pattern and Clone Detail Views in Master-Detail Mode.

ADO.NET Data with a DataAdapter and DataSet

In traditional ADO.NET data binding, you bind your Data Grid to a DataSet. A Data Adapter loads data from the database to the DataSet. Use the Data Adapter’s Update method to post grid changes to the database.

csharp
using DevExpress.XtraGrid.Views.Base;
//. . .
ColumnView view = gridControl1.FocusedView as ColumnView;
view.CloseEditor();
if(view.UpdateCurrentRow()) {
    sqlDataAdapter1.Update(myDataSet, MyTable);
}
//. . .
vb
Imports DevExpress.XtraGrid.Views.Base
'. . .
Private view As ColumnView = TryCast(gridControl1.FocusedView, ColumnView)
view.CloseEditor()
If view.UpdateCurrentRow() Then
    sqlDataAdapter1.Update(myDataSet, MyTable)
End If
'. . .

Note

To save changes, the Data Adapter must generate INSERT, UPDATE, and DELETE commands.

Read the following help topics for more information:

Entity Framework

When you bind to Entity Framework and Entity Framework Core models, the Data Grid is bound to a DbContext object. Call the SaveChanges or SaveChangesAsync method to post changes to an underlying data source.

csharp
DXApplication.AdventureWorksDW2008R2Entities dbContext;

private void gridView1_RowUpdated(object sender, DevExpress.XtraGrid.Views.Base.RowObjectEventArgs e) {
    dbContext.SaveChanges();
}
vb
Private dbContext As DXApplication.AdventureWorksDW2008R2Entities

Private Sub gridView1_RowUpdated(ByVal sender As Object, ByVal e As DevExpress.XtraGrid.Views.Base.RowObjectEventArgs)
    dbContext.SaveChanges()
End Sub

Read the following help topic for more information: Tutorial: Entity Framework Data.

Entity Framework Core

EF Core utilizes a DbContext class that differs from the class used for the standard Entity Framework.

csharp
DXApplication.AdventureWorks2014Entities dbContext;

private void gridView1_RowUpdated(object sender, DevExpress.XtraGrid.Views.Base.RowObjectEventArgs e) {
    dbContext.SaveChanges();
}
vb
Private dbContext As DXApplication.AdventureWorks2014Entities

Private Sub gridView1_RowUpdated(ByVal sender As Object, ByVal e As DevExpress.XtraGrid.Views.Base.RowObjectEventArgs)
    dbContext.SaveChanges()
End Sub

Read the following help topic for more information: Binding to Entity Framework Core.

Linq to SQL

In Linq to SQL binding, a Data Grid’s data source is an object of the DataContext class. Utilize its SubmitChanges method to save changes.

csharp
System.Data.Linq.DataContext context;

private void Form1_FormClosing(object sender, FormClosingEventArgs e) {
    context.SubmitChanges();
}
vb
Private context As System.Data.Linq.DataContext

Private Sub Form1_FormClosing(ByVal sender As Object, ByVal e As FormClosingEventArgs)
    context.SubmitChanges()
End Sub

Read the following help topics for more information:

eXpress Persistent Objects (XPO)

To post changes to a data source, call the UnitOfWork.CommitChanges method. If you work with sessions, changes are posted to the data source automatically when persistent objects are saved.

Read the following help topics for more information:

OData

Binding to Open Data sources requires a Microsoft.OData.Client.DataServiceQuery table stored within a Microsoft.OData.Client.DataServiceContext object. To save Data Grid edits, you need to utilize DataServiceContext API such as the DeleteObject or UpdateObject method. These methods send corresponding HTTP queries after you call the DataServiceContext.SaveChanges method. The code for these HTTP queries must be added to the back-end application.

csharp
//server-side code
using System.Data.Entity;
using System.Data.Entity.Infrastructure;
using System.Linq;
using System.Net;
using System.Threading.Tasks;
using System.Web.Http;
using System.Web.OData;
using WebApplication1.Models;

namespace WebApplication1.Controllers {
    public class ProductsController : ODataController {
        ProductsContext db = new ProductsContext();
        private bool ProductExists(int key) {
            return db.Products.Any(p => p.Id == key);
        }

        // . . .

        //HTTP POST
        public async Task<IHttpActionResult> Post(Product product) {
            if (!ModelState.IsValid) {
                return BadRequest(ModelState);
            }
            db.Products.Add(product);
            await db.SaveChangesAsync();
            return Created(product);
        }
        //HTTP PATCH
        public async Task<IHttpActionResult> Patch([FromODataUri] int key, Delta<Product> product) {
            if (!ModelState.IsValid) {
                return BadRequest(ModelState);
            }
            var entity = await db.Products.FindAsync(key);
            if (entity == null) {
                return NotFound();
            }
            product.Patch(entity);
            try {
                await db.SaveChangesAsync();
            }
            catch (DbUpdateConcurrencyException) {
                if (!ProductExists(key)) {
                    return NotFound();
                }
                else {
                    throw;
                }
            }
            return Updated(entity);
        }
        //HTTP PUT
        public async Task<IHttpActionResult> Put([FromODataUri] int key, Product update) {
            if (!ModelState.IsValid) {
                return BadRequest(ModelState);
            }
            if (key != update.Id) {
                return BadRequest();
            }
            db.Entry(update).State = EntityState.Modified;
            try {
                await db.SaveChangesAsync();
            }
            catch (DbUpdateConcurrencyException) {
                if (!ProductExists(key)) {
                    return NotFound();
                }
                else {
                    throw;
                }
            }
            return Updated(update);
        }
        //HTTP DELETE
        public async Task<IHttpActionResult> Delete([FromODataUri] int key) {
            var product = await db.Products.FindAsync(key);
            if (product == null) {
                return NotFound();
            }
            db.Products.Remove(product);
            await db.SaveChangesAsync();
            return StatusCode(HttpStatusCode.NoContent);
        }
    }
}

//client-side code
using System.Windows.Forms;
using DevExpress.XtraBars.Ribbon;
using DevExpress.XtraGrid.Views.Grid;
using Microsoft.OData.Client;

namespace DXApplication3 {
    public partial class Form1 : RibbonForm {

        DXApplication3.Default.Container container;

        public Form1() {
            InitializeComponent();
            container = new DXApplication3.Default.Container(new System.Uri("http://localhost:53684"));
            productsBindingSource.DataSource = container.Products;
            gridControl1.DataSource = productBindingSource;

            gridControl1.UseEmbeddedNavigator = true;
            gridView1.RowUpdated += GridView1_RowUpdated;
            gridView1.RowDeleting += GridView1_RowDeleting;
            gridView1.OptionsView.NewItemRowPosition = NewItemRowPosition.Top;

            //add a sample row
            var product = new WebApplication1.Models.Product() {
                Name = "Yo-yo",
                Category = "Toys",
                Price = 4.95M
            };
            container.AddObject(product);
        }

        //delete entities from a data source
        private void GridView1_RowDeleting(object sender, DevExpress.Data.RowDeletingEventArgs e) {
            GridView view = sender as GridView;
            WebApplication1.Models.Product entity = e.Row as WebApplication1.Models.Product;
            container.DeleteObject(entity);
            container.SaveChanges();

        }

        //update modified rows
        private void GridView1_RowUpdated(object sender, DevExpress.XtraGrid.Views.Base.RowObjectEventArgs e) {
            GridView view = sender as GridView;
            WebApplication1.Models.Product entity = view.GetFocusedRow() as WebApplication1.Models.Product;
            container.UpdateObject(entity);
            container.SaveChanges();
        }

        //Data Grid does not know whether an OData source is editable, and neither the New Item Row nor the Data Navigator will work
        //In this code, new rows are inserted on button clicks
        private void barButtonItem1_ItemClick(object sender, DevExpress.XtraBars.ItemClickEventArgs e) {
            WebApplication1.Models.Product entity = new WebApplication1.Models.Product();
            container.AddToProducts(entity);
            container.SaveChanges();
            //The HTTP POST will insert the entity into the data source, but the DataServiceContext will not be updated
            //In order to see a new row in the Data Grid, renew your data source connection
            container = new DXApplication3.Default.Container(new System.Uri("http://localhost:53684"));
            productsBindingSource.DataSource = container.Products;
            gridControl1.RefreshDataSource();
        }
    }
}
vb
Imports Microsoft.OData.Client
Imports DevExpress.XtraGrid.Views.Grid
Imports DevExpress.XtraBars.Ribbon
Imports System.Windows.Forms

'server-side code
Imports System.Data.Entity
Imports System.Data.Entity.Infrastructure
Imports System.Linq
Imports System.Net
Imports System.Threading.Tasks
Imports System.Web.Http
Imports System.Web.OData
Imports WebApplication1.Models

Namespace WebApplication1.Controllers
    Public Class ProductsController
        Inherits ODataController

        Private db As New ProductsContext()
        Private Function ProductExists(ByVal key As Integer) As Boolean
            Return db.Products.Any(Function(p) p.Id = key)
        End Function

        ' . . .

        'HTTP POST
        Public Async Function Post(ByVal product As Product) As Task(Of IHttpActionResult)
            If Not ModelState.IsValid Then
                Return BadRequest(ModelState)
            End If
            db.Products.Add(product)
            Await db.SaveChangesAsync()
            Return Created(product)
        End Function
        'HTTP PATCH
        Public Async Function Patch(<FromODataUri> ByVal key As Integer, ByVal product As Delta(Of Product)) As Task(Of IHttpActionResult)
            If Not ModelState.IsValid Then
                Return BadRequest(ModelState)
            End If
            Dim entity = Await db.Products.FindAsync(key)
            If entity Is Nothing Then
                Return NotFound()
            End If
            product.Patch(entity)
            Try
                Await db.SaveChangesAsync()
            Catch e1 As DbUpdateConcurrencyException
                If Not ProductExists(key) Then
                    Return NotFound()
                Else
                    Throw
                End If
            End Try
            Return Updated(entity)
        End Function
        'HTTP PUT
        Public Async Function Put(<FromODataUri> ByVal key As Integer, ByVal update As Product) As Task(Of IHttpActionResult)
            If Not ModelState.IsValid Then
                Return BadRequest(ModelState)
            End If
            If key <> update.Id Then
                Return BadRequest()
            End If
            db.Entry(update).State = EntityState.Modified
            Try
                Await db.SaveChangesAsync()
            Catch e1 As DbUpdateConcurrencyException
                If Not ProductExists(key) Then
                    Return NotFound()
                Else
                    Throw
                End If
            End Try
            Return Updated(update)
        End Function
        'HTTP DELETE
        Public Async Function Delete(<FromODataUri> ByVal key As Integer) As Task(Of IHttpActionResult)
            Dim product = Await db.Products.FindAsync(key)
            If product Is Nothing Then
                Return NotFound()
            End If
            db.Products.Remove(product)
            Await db.SaveChangesAsync()
            Return StatusCode(HttpStatusCode.NoContent)
        End Function
    End Class
End Namespace

'client-side code

Namespace DXApplication3
    Partial Public Class Form1
        Inherits RibbonForm

        Private container As DXApplication3.Default.Container

        Public Sub New()
            InitializeComponent()
            container = New DXApplication3.Default.Container(New System.Uri("http://localhost:53684"))
            productsBindingSource.DataSource = container.Products
            gridControl1.DataSource = productBindingSource

            gridControl1.UseEmbeddedNavigator = True
            AddHandler gridView1.RowUpdated, AddressOf GridView1_RowUpdated
            AddHandler gridView1.RowDeleting, AddressOf GridView1_RowDeleting
            gridView1.OptionsView.NewItemRowPosition = NewItemRowPosition.Top

            'Add a sample row
            Dim product = New WebApplication1.Models.Product() With {.Name = "Yo-yo", .Category = "Toys", .Price = 4.95D}
            container.AddObject(product)
        End Sub

        'Delete entities from a data source
        Private Sub GridView1_RowDeleting(ByVal sender As Object, ByVal e As DevExpress.Data.RowDeletingEventArgs)
            Dim view As GridView = TryCast(sender, GridView)
            Dim entity As WebApplication1.Models.Product = TryCast(e.Row, WebApplication1.Models.Product)
            container.DeleteObject(entity)
            container.SaveChanges()

        End Sub

        'Update modified rows
        Private Sub GridView1_RowUpdated(ByVal sender As Object, ByVal e As DevExpress.XtraGrid.Views.Base.RowObjectEventArgs)
            Dim view As GridView = TryCast(sender, GridView)
            Dim entity As WebApplication1.Models.Product = TryCast(view.GetFocusedRow(), WebApplication1.Models.Product)
            container.UpdateObject(entity)
            container.SaveChanges()
        End Sub

        'Data Grid does not know whether an OData source is editable, and neither the New Item Row nor the Data Navigator will work
        'In this code, new rows are inserted on button clicks
        Private Sub barButtonItem1_ItemClick(ByVal sender As Object, ByVal e As DevExpress.XtraBars.ItemClickEventArgs)
            Dim entity As New WebApplication1.Models.Product()
            container.AddToProducts(entity)
            container.SaveChanges()
            'The HTTP POST will insert the entity into the data source, but the DataServiceContext will not be updated
            'In order to see a new row in the Data Grid, renew your data source connection
            container = New DXApplication3.Default.Container(New System.Uri("http://localhost:53684"))
            productsBindingSource.DataSource = container.Products
            gridControl1.RefreshDataSource()
        End Sub
    End Class
End Namespace

We do not recommend in-place editing when a Data Grid is bound to a server-side data source, including Open Data sources. Instead, create a substitute source (for example, a BindingList populated from an OData source).

Read the following help topics for more information:

See Also

Grid Control - Data Binding