Skip to main content

Post Data to an Underlying Data Source

  • 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.

using DevExpress.XtraGrid.Views.Base;
//. . .
ColumnView view = gridControl1.FocusedView as ColumnView;
view.CloseEditor();
if(view.UpdateCurrentRow()) {
    sqlDataAdapter1.Update(myDataSet, MyTable);
}
//. . .

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.

DXApplication.AdventureWorksDW2008R2Entities dbContext;

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

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.

DXApplication.AdventureWorks2014Entities dbContext;

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

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.

System.Data.Linq.DataContext context;

private void Form1_FormClosing(object sender, FormClosingEventArgs e) {
    context.SubmitChanges();
}

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.

//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();
        }
    }
}

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