Persisting Data in Server

21 Dec 202213 minutes to read

Edited data can be persisted in the database using the RESTful web services.

All the CRUD operations in the treegrid are done through DataManager. The DataManager has an option to bind all the CRUD related data in server-side.

NOTE

For your information, the ODataAdaptor persists data in the server as per OData protocol.

In the following section, we have explained how to perform CRUD operation in server-side using the UrlAdaptor and RemoteSave Adaptor.

URL adaptor

You can use the UrlAdaptor of DataManager when binding data source from remote data.
In the initial load of grid, data are fetched from remote data and bound to the grid using url property of DataManager.
You can map The CRUD operation in grid can be mapped to server-side Controller actions using the properties InsertUrl, RemoveUrl, UpdateUrl and BatchUrl.

The following code example describes the above behavior.

@using Syncfusion.EJ2.Grids

@(Html.EJS().TreeGrid("TreeGrid").DataSource(dataManager => { dataManager.Url("/Home/UrlDatasource").InsertUrl("/Home/Insert").UpdateUrl("/Home/Update")
      .RemoveUrl("/Home/Remove").BatchUrl("/Home/Delete").Adaptor("UrlAdaptor"); })
  .EditSettings(edit =>
   {
    edit.AllowAdding(true);
    edit.AllowDeleting(true);
    edit.AllowEditing(true);
    edit.Mode(Syncfusion.EJ2.TreeGrid.EditMode.Row);
    edit.NewRowPosition(Syncfusion.EJ2.TreeGrid.RowPosition.Below);
   })
  .HasChildMapping("isParent").IdMapping("TaskID").ParentIdMapping("ParentItem")
  .Toolbar(new List<string>() { "Add", "Edit", "Delete", "Update", "Cancel" })
  .Columns(col =>
   {
      col.Field("TaskID").HeaderText("Task ID").IsPrimaryKey(true).Width(110).TextAlign(TextAlign.Right)
      .ValidationRules(new { required = true, number = true }).Add();
      col.Field("TaskName").HeaderText("Task Name").Width(190).Add();
      col.Field("Duration").HeaderText("Duration").Width(210).Add();
      col.Field("Progress").HeaderText("Progress").Width(210).Add();

   }).Height(400).TreeColumnIndex(1).Render()
)
public ActionResult DataSource(DataManager dm)
{
    var DataSource = TreeData.GetTree();
    DataOperations operation = new DataOperations();
    if (dm.Where != null && dm.Where.Count > 0)
    {
        DataSource = operation.PerformFiltering(DataSource, dm.Where, "and");  //perform Filtering based on query passed as well as maintain child records Expand/Collapse
    }
    var count = DataSource.ToList<TreeData>().Count();
    if (dm.Skip != 0)
    {
        DataSource = operation.PerformSkip(DataSource, dm.Skip);   //Paging
    }
    if (dm.Take != 0)
    {
        DataSource = operation.PerformTake(DataSource, dm.Take);
    }
    return dm.RequiresCounts ? Json(new { result = DataSource, count = count }) : Json(DataSource);
}

Also, when using the UrlAdaptor, you need to return the data as JSON from the controller action and the JSON object must contain a property as result with dataSource as its value and one more property count with the dataSource total records count as its value.

Insert record

Using the InsertUrl property, you can specify the controller action mapping URL to perform insert operation on the server-side.

The following code example describes the above behavior.

@using Syncfusion.EJ2.Grids

@(Html.EJS().TreeGrid("TreeGrid").DataSource(dataManager => { dataManager.Url("/Home/UrlDatasource").InsertUrl("/Home/Insert").UpdateUrl("/Home/Update")
      .RemoveUrl("/Home/Remove").BatchUrl("/Home/Delete").Adaptor("UrlAdaptor"); })
  .EditSettings(edit =>
   {
    edit.AllowAdding(true);
    edit.AllowDeleting(true);
    edit.AllowEditing(true);
    edit.Mode(Syncfusion.EJ2.TreeGrid.EditMode.Row);
    edit.NewRowPosition(Syncfusion.EJ2.TreeGrid.RowPosition.Below);
   })
  .HasChildMapping("isParent").IdMapping("TaskID").ParentIdMapping("ParentItem")
  .Toolbar(new List<string>() { "Add", "Edit", "Delete", "Update", "Cancel" })
  .Columns(col =>
   {
      col.Field("TaskID").HeaderText("Task ID").IsPrimaryKey(true).Width(110).TextAlign(TextAlign.Right)
      .ValidationRules(new { required = true, number = true }).Add();
      col.Field("TaskName").HeaderText("Task Name").Width(190).Add();
      col.Field("Duration").HeaderText("Duration").Width(210).Add();
      col.Field("Progress").HeaderText("Progress").Width(210).Add();

   }).Height(400).TreeColumnIndex(1).Render()
)
public ActionResult Insert(TreeGridData value, int relationalKey)
{
    var i = 0;
    for (; i < TreeData.tree.Count; i++)
    {
        if (TreeData.tree[i].TaskID == relationalKey)
        {
            break;
        }
    }
    i += FindChildRecords(relationalKey); // Inserted new record when newRowPosition API is in "Below".
    TreeData.tree.Insert(i + 1, value);
}

public int FindChildRecords(int id)
{
    var count = 0;
    for (var i = 0; i < TreeData.tree.Count; i++)
    {
        if (TreeData.tree[i].ParentItem == id)
        {
            count++;
            count += FindChildRecords(TreeData.tree[i].TaskID);
        }
    }
    return count;
}

The newly added record details are bound to the value parameter and relationalKey contains primaryKey value of an selected record helps to find out the position of newly added record. Refer to the following screenshot.

Insert

Update record

Using the UpdateUrl property, the controller action mapping URL can be specified to perform save/update operation on the server-side.

The following code example describes the previous behavior.

@using Syncfusion.EJ2.Grids

@(Html.EJS().TreeGrid("TreeGrid").DataSource(dataManager => { dataManager.Url("/Home/UrlDatasource").InsertUrl("/Home/Insert").UpdateUrl("/Home/Update")
      .RemoveUrl("/Home/Remove").BatchUrl("/Home/Delete").Adaptor("UrlAdaptor"); })
  .EditSettings(edit =>
   {
    edit.AllowAdding(true);
    edit.AllowDeleting(true);
    edit.AllowEditing(true);
    edit.Mode(Syncfusion.EJ2.TreeGrid.EditMode.Row);
    edit.NewRowPosition(Syncfusion.EJ2.TreeGrid.RowPosition.Below);
   })
  .HasChildMapping("isParent").IdMapping("TaskID").ParentIdMapping("ParentItem")
  .Toolbar(new List<string>() { "Add", "Edit", "Delete", "Update", "Cancel" })
  .Columns(col =>
   {
      col.Field("TaskID").HeaderText("Task ID").IsPrimaryKey(true).Width(110).TextAlign(TextAlign.Right)
      .ValidationRules(new { required = true, number = true }).Add();
      col.Field("TaskName").HeaderText("Task Name").Width(190).Add();
      col.Field("Duration").HeaderText("Duration").Width(210).Add();
      col.Field("Progress").HeaderText("Progress").Width(210).Add();

   }).Height(400).TreeColumnIndex(1).Render()
)
public ActionResult Update(TreeGridData value)
{
    var val = TreeData.tree.Where(ds => ds.TaskID == value.TaskID).FirstOrDefault();
    val.TaskName = value.TaskName;
    val.StartDate = value.StartDate;
    val.Duration = value.Duration;
    val.Priority = value.Priority;
    val.Progress = value.Progress;
    return Json(value);
}

The updated record details are bound to the value parameter. Refer to the following screenshot.

Update

Delete record

Using the RemoveUrl and BatchUrl property, the controller action mapping URL can be specified to perform delete operation on the server-side.

The following code example describes the previous behavior.

@using Syncfusion.EJ2.Grids

@(Html.EJS().TreeGrid("TreeGrid").DataSource(dataManager => { dataManager.Url("/Home/UrlDatasource").InsertUrl("/Home/Insert").UpdateUrl("/Home/Update")
      .RemoveUrl("/Home/Remove").BatchUrl("/Home/Delete").Adaptor("UrlAdaptor"); })
  .EditSettings(edit =>
   {
    edit.AllowAdding(true);
    edit.AllowDeleting(true);
    edit.AllowEditing(true);
    edit.Mode(Syncfusion.EJ2.TreeGrid.EditMode.Row);
    edit.NewRowPosition(Syncfusion.EJ2.TreeGrid.RowPosition.Below);
   })
  .HasChildMapping("isParent").IdMapping("TaskID").ParentIdMapping("ParentItem")
  .Toolbar(new List<string>() { "Add", "Edit", "Delete", "Update", "Cancel" })
  .Columns(col =>
   {
      col.Field("TaskID").HeaderText("Task ID").IsPrimaryKey(true).Width(110).TextAlign(TextAlign.Right)
      .ValidationRules(new { required = true, number = true }).Add();
      col.Field("TaskName").HeaderText("Task Name").Width(190).Add();
      col.Field("Duration").HeaderText("Duration").Width(210).Add();
      col.Field("Progress").HeaderText("Progress").Width(210).Add();

   }).Height(400).TreeColumnIndex(1).Render()
)
public ActionResult Remove(int key)
{
    TreeData.tree.Remove(TreeData.tree.Where(ds => ds.TaskID == key).FirstOrDefault());
}

public ActionResult Delete(List<TreeData> changed, List<TreeData> added, List<TreeData> deleted)
{
    for (var i = 0; i < deleted.Count; i++)
    {
        TreeData.tree.Remove(TreeData.tree.Where(ds => ds.TaskID == deleted[i].TaskID).FirstOrDefault());
    }
}

The deleted record primary key value is bound to the key parameter. Refer to the following screenshot.

Delete

While delete parent record, the parent and child records is bound to the deleted parameter. Refer to the following screenshot.

Remove

Remote save adaptor

You may need to perform all Tree Grid Actions in client-side except the CRUD operations, that should be interacted with server-side to persist data. It can be achieved in TreeGrid by using RemoteSaveAdaptor.

Datasource must be set to json property and set RemoteSaveAdaptor to the adaptor property. CRUD operations can be mapped to server-side using updateUrl, insertUrl, removeUrl and batchUrl properties.

You can use the following code example to use RemoteSaveAdaptor in TreeGrid.

@using Syncfusion.EJ2.Grids

@(Html.EJS().TreeGrid("TreeGrid").DataSource(dataManager => { dataManager.Json(ViewBag.dataSource.ToArray()).InsertUrl("/Home/Insert").UpdateUrl("/Home/Update")
      .RemoveUrl("/Home/Remove").BatchUrl("/Home/Delete").Adaptor("RemoteSaveAdaptor"); })
  .EditSettings(edit =>
   {
    edit.AllowAdding(true);
    edit.AllowDeleting(true);
    edit.AllowEditing(true);
    edit.Mode(Syncfusion.EJ2.TreeGrid.EditMode.Row);
    edit.NewRowPosition(Syncfusion.EJ2.TreeGrid.RowPosition.Below);
   })
  .HasChildMapping("isParent").IdMapping("TaskID").ParentIdMapping("ParentItem")
  .Toolbar(new List<string>() { "Add", "Edit", "Delete", "Update", "Cancel" })
  .Columns(col =>
   {
      col.Field("TaskID").HeaderText("Task ID").IsPrimaryKey(true).Width(110).TextAlign(TextAlign.Right)
      .ValidationRules(new { required = true, number = true }).Add();
      col.Field("TaskName").HeaderText("Task Name").Width(190).Add();
      col.Field("Duration").HeaderText("Duration").Width(210).Add();
      col.Field("Progress").HeaderText("Progress").Width(210).Add();

   }).Height(400).TreeColumnIndex(1).Render()
)
public ActionResult Index(DataManager dm)
{
   var data = TreeData.GetTree();
   ViewBag.dataSource = data;
   return View();
}

public ActionResult Insert(TreeGridData value, int relationalKey)
{
    var i = 0;
    for (; i < TreeData.tree.Count; i++)
    {
        if (TreeData.tree[i].TaskID == relationalKey)
        {
            break;
        }
    }
    i += FindChildRecords(relationalKey); // Inserted new record when newRowPosition API is in "Below".
    TreeData.tree.Insert(i + 1, value);
}

public int FindChildRecords(int id)
{
    var count = 0;
    for (var i = 0; i < TreeData.tree.Count; i++)
    {
        if (TreeData.tree[i].ParentItem == id)
        {
            count++;
            count += FindChildRecords(TreeData.tree[i].TaskID);
        }
    }
    return count;
}

public ActionResult Update(TreeGridData value)
{
    var val = TreeData.tree.Where(ds => ds.TaskID == value.TaskID).FirstOrDefault();
    val.TaskName = value.TaskName;
    val.StartDate = value.StartDate;
    val.Duration = value.Duration;
    val.Priority = value.Priority;
    val.Progress = value.Progress;
    return Json(value);
}

public ActionResult Delete(int key)
{
    TreeData.tree.Remove(TreeData.tree.Where(ds => ds.TaskID == key).FirstOrDefault());
}

public ActionResult Remove(List<TreeGridData> changed, List<TreeGridData> added, List<TreeGridData> deleted)
{
    for (var i = 0; i < deleted.Count; i++)
    {
        TreeData.tree.Remove(TreeData.tree.Where(ds => ds.TaskID == deleted[i].TaskID).FirstOrDefault());
    }
}

NOTE

You can refer to our ASP.NET MVC Tree Grid feature tour page for its groundbreaking feature representations. You can also explore our ASP.NET MVC Tree Grid example to knows how to present and manipulate data.