This is a migrated thread and some comments may be shown as answers.

[Solved] DbSortClause expressions must have a type that is order comparable.Parameter name: key

1 Answer 530 Views
Grid
This is a migrated thread and some comments may be shown as answers.
This question is locked. New answers and comments are not allowed.
Carey
Top achievements
Rank 1
Carey asked on 20 Jul 2011, 03:23 AM
I have implemented a server bound grid using Entity Framework to edit/update/delete with paging, sorting, filtering. I attached project and database.

The issue is when I sort on the PROCESS_OBJECT_TYPE column I get this error:
{"DbSortClause expressions must have a type that is order comparable.Parameter name: key"}

When I filter on the PROCESS_OBJECT_TYPE column, the filter operator list is empty and you get this error;
"Object reference not set to an instance of an object."

This column is a type property of the PROCESS_OBJECT which is the model of the view and is not a simple scalar. It uses a display and edit template view for adding/updating new records in the grid with a drop down.

How can I enable sorting or filtering for this column?

View:
@model IEnumerable<TelerikMvcApplication2.PROCESS_OBJECT>
@{
ViewData["Title"] = "Editing Jobs";
}
<h2>@ViewData["Title"]</h2>
<p>
</p>
@{Html.Telerik().Grid<TelerikMvcApplication2.PROCESS_OBJECT>(Model)
.Name("Jobs")
.ToolBar(commands => commands.Insert())
.DataKeys(keys =>
{
keys.Add(c => c.OBJECT_ID);
})
.DataBinding(dataBinding => dataBinding
.Server()
.Select("EditingServerSide", "Job", new { mode = mode, type = type, pageInput = ViewData["pageInput"], nextPrevious = ViewData["nextPrevious"], numeric = ViewData["numeric"], position = position, currentPage = currentPage, pageSize = ViewData["pageSize"] })
.Insert("Insert", "Job", new { mode = mode, type = type, pageInput = ViewData["pageInput"], nextPrevious = ViewData["nextPrevious"], numeric = ViewData["numeric"], position = position, currentPage = currentPage, pageSize = ViewData["pageSize"] })
.Update("Save", "Job", new { mode = mode, type = type, pageInput = ViewData["pageInput"], nextPrevious = ViewData["nextPrevious"], numeric = ViewData["numeric"], position = position, currentPage = currentPage, pageSize = ViewData["pageSize"] })
.Delete("Delete", "Job", new { mode = mode, type = type, pageInput = ViewData["pageInput"], nextPrevious = ViewData["nextPrevious"], numeric = ViewData["numeric"], position = position, currentPage = currentPage, pageSize = ViewData["pageSize"] }))
.Columns(columns =>
{
columns.Bound(o => o.OBJECT_ID).Title("Object ID").ReadOnly(true);
columns.Bound(o => o.PROCESS_OBJECT_TYPE).Title("Object Type"); //.Sortable(false).Filterable(false);
columns.Bound(o => o.OBJECT_NAME).Title("Name");
columns.Command(commands =>
{
commands.Edit();
commands.Delete();
}).Width(200).Title("Action");
})
.Pageable(paging => paging.Style(pagerStyles).Position(position).PageTo(currentPage))
.Editable(editing => editing.Mode(mode))
.Sortable().Filterable().Render();
}


Controller:
{
public class JobController : Controller
{
private BODS_ETL_CONTROLEntities db = new BODS_ETL_CONTROLEntities();
public void setViewData(GridEditMode? mode, GridButtonType? type, bool? pageInput, bool? nextPrevious, bool? numeric, GridPagerPosition? position, int? currentPage, bool? pageSize)
{
ViewData["pageInput"] = pageInput ?? false;
ViewData["nextPrevious"] = nextPrevious ?? true;
ViewData["numeric"] = numeric ?? true;
ViewData["pageSize"] = pageSize ?? false;
ViewData["position"] = position ?? GridPagerPosition.Bottom;
ViewData["currentPage"] = currentPage ?? 1;
ViewData["mode"] = mode ?? GridEditMode.InLine;
ViewData["type"] = type ?? GridButtonType.Text;
}
public ActionResult EditingServerSide(GridEditMode? mode, GridButtonType? type, bool? pageInput, bool? nextPrevious, bool? numeric, GridPagerPosition? position, int? currentPage, bool? pageSize)
{
setViewData(mode,type,pageInput,nextPrevious,numeric,position,currentPage,pageSize);
//Jobs Only
var process_object = db.PROCESS_OBJECT.Include("PROCESS_OBJECT_TYPE").Include("PROCESS_OBJECT_TYPE"); //.Where(o => o.OBJECT_TYPE_ID == 1);
//return View(new GridModel(process_object.ToList()));
PopulateJobTypes();
return View(process_object);
}
[AcceptVerbs(HttpVerbs.Post)]
public ActionResult Insert(GridEditMode mode, GridButtonType type, bool? pageInput, bool? nextPrevious, bool? numeric, GridPagerPosition? position, int? currentPage, bool? pageSize)
{
setViewData(mode, type, pageInput, nextPrevious, numeric, position, currentPage, pageSize);
PROCESS_OBJECT process_object = new PROCESS_OBJECT();
//Query the max ID of the obejcts to set the object id.
//Perform model binding (fill the product properties and validate it).
if (TryUpdateModel(process_object))
{
Int32 id = db.PROCESS_OBJECT.Max(u => u.OBJECT_ID) + 1;
process_object.OBJECT_ID = id;
//Need to attach an existing PROCESS_OBJECT_TYPE entity from the database to this new PROCESS_OBJECT
//otherwise the EF will try to create a new one
//...so lets find the one that matches the type name the user selected
PROCESS_OBJECT_TYPE pot = db.PROCESS_OBJECT_TYPE.First(d => d.OBJECT_TYPE_ID == process_object.PROCESS_OBJECT_TYPE.OBJECT_TYPE_ID);
//assign it to the process_object
process_object.PROCESS_OBJECT_TYPE = pot;
//lets not forget to add the type_id or EF will complain about it
process_object.OBJECT_TYPE_ID = pot.OBJECT_TYPE_ID;
db.PROCESS_OBJECT.AddObject(process_object);
db.SaveChanges();
//GridRouteValues() is an extension method which returns the
//route values defining the grid state - current page, sort expression, filter etc.
RouteValueDictionary routeValues = this.GridRouteValues();
// add the editing mode to the route values
routeValues.Add("mode", mode);
return RedirectToAction("EditingServerSide", routeValues);
}
PopulateJobTypes();
//The model is invalid - render the current view to show any validation errors
return View("EditingServerSide", db.PROCESS_OBJECT.Include("PROCESS_OBJECT_TYPE"));
}
[AcceptVerbs(HttpVerbs.Post)]
public ActionResult Save(int id, string name, GridEditMode mode, GridButtonType type, bool? pageInput, bool? nextPrevious, bool? numeric, GridPagerPosition? position, int? currentPage, bool? pageSize)
{
setViewData(mode, type, pageInput, nextPrevious, numeric, position, currentPage, pageSize);
PROCESS_OBJECT process_object = new PROCESS_OBJECT();
//Perform model binding (fill the product properties and validate it).
//Exclude "PROCESS_OBJECT_TYPE from the list of updated properties
if (TryUpdateModel(process_object))
{
//Need to get this cloned object to update the real one in the entity context.
//Need to attach an existing PROCESS_OBJECT_TYPE entity from the database to this new PROCESS_OBJECT
//otherwise the EF will try to create a new one
//...so lets find the one that matches the type name the user selected
PROCESS_OBJECT_TYPE pot = db.PROCESS_OBJECT_TYPE.First(d => d.OBJECT_TYPE_ID == process_object.PROCESS_OBJECT_TYPE.OBJECT_TYPE_ID);
//assign it to the process_object
process_object.PROCESS_OBJECT_TYPE = pot;
//lets not forget to add the type_id or EF will complain about it
process_object.OBJECT_TYPE_ID = pot.OBJECT_TYPE_ID;
//Through trial and error I found that on update the object is in fact already loaded
//but I had to manually mark the previously detached object as modified
db.ObjectStateManager.ChangeObjectState(process_object, EntityState.Modified);
//...then use this method to actually apply the changes...
//Without doing both this, the object never updates in the database
db.SaveChanges();
//GridRouteValues() is an extension method which returns the
//route values defining the grid state - current page, sort expression, filter etc.
RouteValueDictionary routeValues = this.GridRouteValues();
// add the editing mode to the route values
routeValues.Add("mode", mode);
return RedirectToAction("EditingServerSide", routeValues);
}
PopulateJobTypes();
//The model is invalid - render the current view to show any validation errors
return View("EditingServerSide", db.PROCESS_OBJECT.Include("PROCESS_OBJECT_TYPE"));
}
private void PopulateJobTypes()
{
ViewData["process_object_types"] =
db.PROCESS_OBJECT_TYPE.Select(e => new
{
Name = e.OBJECT_TYPE_NAME,
Id = e.OBJECT_TYPE_ID
})
.OrderBy(e => e.Name);
}
}
}


Thanks

1 Answer, 1 is accepted

Sort by
0
Bill
Top achievements
Rank 1
answered on 28 Oct 2011, 06:28 AM
Other posts suggest using custom binding to solve this problem.  Im not sure how to do that so I too would like a solution.  It would be nice if there were a clean way to specify the simple type field in the complex type to sort and filter by as a GridBoundColumnBuilder, i.e.

columns.Bound(o => o.MyChild_ComplexType)
  .Title(

"Child");
    .Width(100);
    .FilterBy("MyChildName");
 .SortBy("MyChildName");

 

Tags
Grid
Asked by
Carey
Top achievements
Rank 1
Answers by
Bill
Top achievements
Rank 1
Share this question
or