Work with enumerations in Asp MVC Telerik Grid and Entity Framework

For a web application in development (ASP.Net MVC) I use the telerik grid. The grid is bound to the IQueryable of my list, because it is a large table, and I want telerik to apply its filter in the list, and then execute this result without loading 10'000 rows (with joined tables), and then with the filter, use only strings.

I use (and I really need this for this page, this is one of the key functions) filter / grid order.

One of the main columns (data type definition) is an enumeration.

The problem is that I get the "Specified type member is not supported in linq to entities" as soon as I try to filter / sort it.

I need to bind it to an enumeration (and not the displayed int), because if I use id, filter / order by will be on int, and I cannot expect the user to know the identifier of the external table.

I just can’t realize myself again for all the parameters of the grids (located in the URL) (I assume that this is either me doing everything or nothing) and filtering it correctly, ordering it correctly).

Do you have an idea for a workaround?

+4
source share
2 answers

I don’t know what your Entity model looks like, but I suppose you have something like this model:

 public partial class Project { public int Id { get; set; } public string Name { get; set; } public int Status { get; set; } } 

and the Status property represents your enumeration value, then you have this enumeration:

 public enum ProjectStatuses { Current = 1, Started = 2, Stopped = 3, Finished = 4, } 

Then just create a new ViewModel like this:

 public class ProjectDetails { public int Id { get; set; } public string Name { get; set; } public int Status { get; set; } public ProjectStatuses StatusValue { get { return (ProjectStatuses) Status; } } // This property to display in telerik ClientTemplate public string StatusName { get { return Enum.GetName(typeof (ProjectStatuses), Status ); } } } 

And since I like extension methods, I will add the following:

 public static class ModelListExtensions { public static IQueryable<ProjectDetails> ToViewModelDetails(this IQueryable<Project> modelList) { return modelList.Select(m => new ProjectDetails { Id = m.Id, Name = m.Name, Status = m.Status, }; } } 

Update:

Here is the controller

  public ActionResult Index() { int total; var viewModel = getGridList(out total); ViewBag.Total = total; return View(viewModel); } //this Action to get ajax pages [GridAction(EnableCustomBinding = true)] public ActionResult ReGetIndex(GridCommand command, int roleId) { int total; var list = getGridList(out total, roleId, command); return View(new GridModel {Data = list, Total = total}); } private IEnumerable<ProjectDetails> getGridList(out int total, GridCommand command = null) { command = command ?? new GridCommand {Page = 1}; foreach (var descriptor in command.SortDescriptors) { if (descriptor.Member == "StatusValue") descriptor.Member = "Status"; } foreach (FilterDescriptor descriptor in command.FilterDescriptors) { if (descriptor.Member == "StatusValue") descriptor.Member = "Status"; } var list = modelService.AllAsQuery() .ToViewModelDetails() // To convert it to our ViewModel if we have one .Where(command.FilterDescriptors); total = list.Count(); return (IEnumerable<ProjectDetails>) list.Sort(command.SortDescriptors) .Page(command.Page - 1, command.PageSize) .GroupBy(command.GroupDescriptors).ToIList(); } 

And this is a view

 @model IEnumerable<ProjectDetails> @{ Html.Telerik() .Grid(Model) .Name("ProjectsGrid") .Sortable() .Filterable() .EnableCustomBinding(true) .DataBinding(dataBinding => dataBinding .Ajax() .Select("ReGetIndex", "Projects")) .Pageable(page => page.Style(GridPagerStyles.PageSizeDropDown | GridPagerStyles.NextPreviousAndNumeric).Total(ViewBag.Total)) .Columns(column => { column.Bound(m => m.Id).Hidden(true); column.Bound(m => m.Name); column.Bound(m => m.StatusValue).ClientTemplate("<#= StatusName #>"); }) .Render(); } 

Update:

If you want to apply at least one sort order, you can use something like this:

  if (!command.SortDescriptors.Any()) { command.SortDescriptors.Add(new SortDescriptor {Member = "YourDefaultProperty"}); } 
+5
source

You really have no choice (or a few annoying options)

Weather, you use the class instead of enum (but if you used an enumeration, it was because it was better).

Or you "pseudo-sort" your enum and use the displayed int.

 public enum TT { Brown = 0, Green = 1 } 

Of course, you will need to check the actual data (matched int) in your database and update it so that it matches the new order (cannot change the order of enumeration without impact). And you will have to do this every time you want to insert a value between existing enumeration values.

Or are you waiting for the next version of EF / linq / C #, which should have enumeration support in linq2entities

0
source

Source: https://habr.com/ru/post/1411485/


All Articles