Post Data to an Underlying Data Source
- 8 minutes to read
- Common Tips
- ADO.NET Data with a DataAdapter and DataSet
- Entity Framework
- Entity Framework Core
- Linq to SQL
- eXpress Persistent Objects (XPO)
- OData
Common Tips
Regardless of the data binding method, changes to an underlying source should typically be posted on the following events.
-
Occurs after an end-user has finished modifying a row and tries to navigate to another row. RowUpdated does not fire while the editor is still active (BaseView.IsEditing), so to push changes you need to close this editor first (BaseView.CloseEditor) and call the BaseView.UpdateCurrentRow method to trigger this event manually.
ColumnView.InitNewRow, ColumnView.RowDeleted
Occurs when end-users add or remove Data Grid rows.
Form.Closing
A standard WinForms event that allows you to avoid excessive updates and save all changes at once before closing an application.
ADO.NET Data with a DataAdapter and DataSet
In traditional ADO.NET data binding, your Data Grid is bound to a Data Set, populated from an underlying data source by a Data Adapter. In this case, to post changes back to an underlying data source, call the Adapter’s Update method.
using DevExpress.XtraGrid.Views.Base;
//. . .
ColumnView view = gridControl1.FocusedView as ColumnView;
view.CloseEditor();
if(view.UpdateCurrentRow()) {
sqlDataAdapter1.Update(myDataSet, MyTable");
}
//. . .
Note that to save changes, an Adapter must generate INSERT, UPDATE and DELETE commands.
Entity Framework
When binding to the Entity Framework and Entity Framework Core models, the Data Grid is bound to a DbContext object. Call the SaveChanges or SaveChangesAsync methods 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();
}
Note
See Also Tutorial: Entity Framework Data
Entity Framework Core
EF Core utilizes a different class of a DbContext than the one used for regular Entity Framework.
DXApplication.AdventureWorks2014Entities dbContext;
private void gridView1_RowUpdated(object sender, DevExpress.XtraGrid.Views.Base.RowObjectEventArgs e) {
dbContext.SaveChanges();
}
Note
See Also 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();
}
Note
See Also Binding to LINQ to SQL Classes
How to save changes made in the GridControl in the LINQ to SQL database
eXpress Persistent Objects (XPO)
To post changes to a data source, call the UnitOfWork.CommitChanges method. When working with sessions, the saving of persistent objects posts changes to the data source automatically.
Note
See Also eXpress Persistent Objects
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 the DataServiceContext API: methods like DeleteObject or UpdateObject. These methods will send corresponding HTTP queries after you call the DataServiceContext.SaveChanges method.The code for these HTTP queries must be added to a 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);
}
//deleting 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();
}
//updating 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 an OData source is editable and both New Item Row and Data Navigator will not 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 to the data source, but the DataServiceContext will not be updated
//in order to see a new row in Data Grid, renew your data source connection
container = new DXApplication3.Default.Container(new System.Uri("http://localhost:53684"));
productsBindingSource.DataSource = container.Products;
gridControl1.RefreshDataSource();
}
}
}
Note that implementing in-place editing when the Data Grid is bound to a server-side data source, including Open Data sources, is not recommended. A preferable approach for this scenario is to make a substitute Data Grid source (e.g., a BindingList object populated from an OData source).