Doing CRUD Operations with Infragistics UltraGrid and Entity Framework

[Infragistics] Mihail Mateev / Monday, March 2, 2015

The Infragistics Windows Form controls are some of the best, most extensible third party controls that I have ever used for UI development.  The set of controls is quite comprehensive and the API is exhaustive.  You can do anything with these controls, in terms of overriding their function and form.

Based on my experience often very good components are designed to be used with some frameworks in the best way, but because IT industry is very dynamic often other new technologies stays most popular and developers look for the best practices to use existing good controls with latest frameworks.

Since I use (and tweak) the UltraGrid control most often, I have decided to create a short article sharing my experience with Infragistics UltraGrid API and probably the most popular ORM for .Net applications – Microsoft Entity Framework. Samples in this post use Infragistics Windows Forms Controls (part of Infragistics Ultimate vol.14.2), EF 6.1.2 / Database First Approach (you can download this version from this link) It is also possible to use NuGet package manager. The data source is based on the popular Northwind sample database. Database engine is SQLServer 2014 Express.

Considerations:

As it was mentioned above, UltraGrid is popular well designed and tested component, released for the first time several years ago. Natively it is designed to work easily with ADO.Net framework and uses data sources like ADO.Net DataTable.

If you want to use Entity Framework there are several specific things that you need to consider first to implement the basic :CRUD (Create, read, update and delete) operations. Most notably: Entities generated from Entity Framework are not native data sources, so it is not possible to bind them directly.

Sample and most important snippets:

For this sample, let's use a simple Windows Forms solution created with Visual Studio 2013 Update 4, including UltraGrid and Entity Framework model, based on Northwind using only a Products table/entity. When we use tables with relations we need to consider integrity rules when trying to update the data source.

 

The structure of the Product entity is shown below:

You need to initialize our EF model:

 1: #region members
 2:  
 3: ObservableCollection data; 
 4: static NORTHWNDEntities model = new NORTHWNDEntities();
 5:  
 6: #endregion members

 

Read operation:

ObservableCollection or List are some of the collections that you can use as a DataSource for UltraGrid.

 1: public Form1()
 2: {
 3:     InitializeComponent();
 4:     data = new ObservableCollection(model.Products.ToList());
 5:     ultraGrid1.DataSource = data;
 6: }

 

Now you can see records in your Infragistics grid. Actually, you cannot apply other CRUD operations on this data source and update database out of the box – you need to add some code.

 

Update operation:

Update operation works with the grid and binds as a data source collection (you just need to set your Windows Forms grid in edit mode), but because we're using Entity Framework, this data source is decoupled. So you need to add code where you want to update the entities from the model and to set their EntityState to Modified. The current sample demonstrates how to update all entities. If you have many records, it is recommended to add additional logic to update only the entities which are changed.

 1: /// 
 2: /// Handles the Click event of the btnUpdateData control.
 3: /// 
 4: ///The source of the event.
 5: ///The  instance containing the event data.
 6: private void btnUpdateData_Click(object sender, EventArgs e)
 7: {
 8:     var product = data.FirstOrDefault();
 9:     var id = product.ProductID;
 10:  
 11:     foreach (Product newproduct in data)
 12:     {
 13:         var oldProduct = model.Products.Where(x => x.ProductID == newproduct.ProductID).FirstOrDefault();
 14:         if (oldProduct != null)
 15:         {
 16:             oldProduct = newproduct;
 17:             model.Entry(oldProduct).State = EntityState.Modified;
 18:         }
 19:         else
 20:         {
 21:             model.Products.Add(newproduct);
 22:         }
 23:     }
 24: }

Finally you need to save changes in your database using SaveChanges() method.

The screenshot below demonstrates how to update data source using this sample application.

 

Create operation:

You can create a new record using the "add new record" option of the UltraGrid (it offers a button for this out of the box). Unfortunately this approach doesn't work with most data sources, so the best approach is programmatically to add a new element in the collection that you are using as a data source and to rebind it to the grid (see the snippet below):

 1: /// 
 2: /// Handles the Click event of the btnAddRow control.
 3: /// 
 4: ///The source of the event.
 5: ///The  instance containing the event data.
 6: private void btnAddRow_Click(object sender, EventArgs e)
 7: {
 8:  
 9:     var newid = data.Select(x => x.ProductID).Max();
 10:     data.Add(new Product { ProductID = newid + 1 });
 11:     ultraGrid1.DataBind();
 12: }

 

The screens below demonstrate how to do that via UI of the sample application.

 

 

Delete operation:

The Delete operation is not offered out of the box from the UI. When you need to delete the selection, you need to get the selected records using Selected.Rows, get the entity from each entity using the ListObect propery of the row, and you need to set the EnttyState.Deleted value. At the end you need to save the changes to the database.

 1: /// 
 2: /// Handles the Click event of the btnDelete control.
 3: /// 
 4: ///The source of the event.
 5: ///The  instance containing the event data.
 6: private void btnDelete_Click(object sender, EventArgs e)
 7: {
 8:     if (this.ultraGrid1.Selected.Rows.Count > 0)
 9:     {
 10:         // Delete the selected rows by calling DeleteSelectedRows.
 11:         Product currProduct = null;
 12:         
 13:         foreach(var curr in this.ultraGrid1.Selected.Rows){
 14:             currProduct = curr.ListObject as Product;
 15:  
 16:             if (currProduct != null)
 17:             {
 18:                 var oldProduct = model.Products.Where(x => x.ProductID == currProduct.ProductID).FirstOrDefault();
 19:                 if (oldProduct != null)
 20:                 {
 21:                     model.Entry(oldProduct).State = EntityState.Deleted;
 22:                     model.Products.Remove(oldProduct);
 23:                 }
 24:             }
 25:         }
 26:  
 27:         this.ultraGrid1.DeleteSelectedRows();
 28:         model.SaveChanges();                  
 29:     }
 30:     else
 31:     {
 32:         // Show a message if there are no selected rows.
 33:         MessageBox.Show("There are no rows selected. Select rows first.");
 34:     }
 35: }

You can use T-SQL expressions using ExecureSQLCommand() method, which affects the database directly. It is possible to apply it without making changes in the model and saving it. This approach is faster, but you need to be very careful here because it doesn’t keep the consistency between the database and the entity model.

 1: if (oldProduct != null)
 2: {
 3:     model.Entry(oldProduct).State = EntityState.Deleted;
 4:     model.Database.ExecuteSqlCommand("delete from dbo.Products where ProductId="+oldProduct.ProductID);
 5: }

The screenshots below demonstrates how to delete records/entities using the sample application, related to this post. 

  

 

This article covers the basic CRUD operations, realized with Infragistics WinForms grid and Entity Framework - and to make the most of this post, be sure to download the source code of this sample here.

You'll also need the Northwind sample database, which you can get in SQLServer 2008 or newer through the CodePlex website. It is also possible also to download a version that's compatible with older versions of Microsoft SQL server from the Microsoft download center.

To play around with the Infragistics Windows Forms dashboards on your own, be sure to get Infragistics Ultimate and see the chart in action in our latest sample application by clicking the banner below!