I'm using Telerik Grid MVC control. I use partial class to extend the entities generate by EFv1. I found the code doesn't work with following exception even I do not call the extended properties in the view:
The specified type member 'IsFinished' is not supported in LINQ to Entities. Only initializers, entity members, and entity navigation properties are supported.
Should the grid control ignore those properties not used in the view and is that a bug?
Thanks!
19 Answers, 1 is accepted
I couldn't reproduce this issue. Find attached my test project and please let me know if I am missing something important.
Regards,
Atanas Korchev
the Telerik team
Do you want to have your say when we set our development plans? Do you want to know when a feature you care about is added or when a bug fixed? Explore the Telerik Public Issue Tracking system and vote to affect the priority of the items.

I have discovered the same issue. The problem is when the entity class is appended with additional properties and it is forwarded to Telerik grid control. It seems that telerik grid tries to provide all entity properties via LINQ and doesn't skip non-entity properties.
E.g.
Entity sample (MyEntity.cs):
[Serializable] |
public partial class MyEntity : IEntity |
{ |
#region Primitive Properties |
public virtual int Id |
{ |
get; |
set; |
} |
public virtual double MyProperty |
{ |
get; |
set; |
} ... |
} |
Extended entity (MyEntityMetadata.cs):
public partial class MyEntity |
{ |
public virtual double AdditionalProperty |
{ |
get { return 1D; } |
} |
} |
Control sample (MyEntity.ascx):
<%@ Control Language="C#" Inherits="System.Web.Mvc.ViewUserControl<System.Linq.IQueryable<MyEntity>>" %> |
<%@ Import Namespace="Telerik.Web.Mvc.UI.Fluent" %> |
<% |
var gridModel = (ViewData["GridModel"] as CustomGridModel) ?? CustomGridModel.GetDefaultInstance(); |
%> |
<% Html.Telerik().Grid(Model) |
.Name(gridModel.Name) |
.DataKeys(keys => keys.Add(c => c.Id)) |
.Columns(columns => |
{ |
columns.Bound(p => p.Id).Hidden(true); |
columns |
.Template(a => |
{ |
%> |
<%= |
Html.CheckBox("checkedRecords" + gridModel.Name, false, new |
{ |
value = a.Id |
}) |
%> |
<% |
}) |
.Title("Check") |
.Width(50) |
.HtmlAttributes(new |
{ |
@class = "not-clickable checkbox-parent", |
style = "text-align:center" |
}); |
columns.Bound(p => p.Id); |
}) |
.ClientEvents(events => |
{ |
if (gridModel.OnRowSelected != "navigateToRowItem" && gridModel.OnRowSelected != "navigateToRootRowItem") |
{ |
events |
.OnRowSelected(gridModel.OnRowSelected); |
} |
events |
.OnLoad("on" + gridModel.Name + "Load"); |
}) |
.Selectable() |
.Pageable() |
.Sortable() |
.Scrollable() |
.Groupable() |
.Filterable().Render(); |
%> |
<%if (gridModel.OnRowSelected == "navigateToRootRowItem") |
{%> |
<script type="text/javascript"> |
function navigateToRootRowItem<%=gridModel.Name %>(e) { |
var id = $(this).siblings().first().html(); |
var url = '<%= Url.Action("Single", "MyEntity", new {id=-1}) %>'.replace('-1', id); |
location.href = url; |
} |
function on<%=gridModel.Name %>Load(e) { |
$("#<%=gridModel.Name %> .t-grid-content .t-state-selected td:not(.not-clickable)").live("click", navigateToRootRowItem<%=gridModel.Name %>); |
} |
</script> |
<%} |
else if (gridModel.OnRowSelected == "navigateToRowItem") |
{%> |
<script type="text/javascript"> |
function navigateToRowItem<%=gridModel.Name %>(e) { |
var id = $(this).siblings().first().html(); |
location.href = currentControllerPath + id; |
} |
function on<%=gridModel.Name %>Load(e) { |
$("#<%=gridModel.Name %> .t-grid-content .t-state-selected td:not(.not-clickable)").live("click", navigateToRowItem<%=gridModel.Name %>); |
} |
</script> |
<% |
}%> |
Controller sample:
public class MyEntityController : EntityController<MyEntity> |
{ |
private IMyEntityService _myEntity; |
public MyEntityController(IMyEntityService myEntity) |
{ |
_myEntity = myEntity; |
} |
public ActionResult List() |
{ |
// returns IQueryable<MyEntity> |
return View(_myEntity.QMyEntity()); |
} |
public ActionResult Single(int id) |
{ |
return View(_myEntity.QMyEntity().Select(p => p.Id == id)); |
} |
[HttpPost] |
public ActionResult Single(MyEntity model) |
{ |
if (TryUpdateModel(model)) |
{ |
try |
{ |
_myEntity.UpdateMyEntity(model); |
return RedirectToAction("List"); |
} |
catch (Exception e) |
{ |
return View(model); |
} |
} |
return View(model); |
} |
} |
View sample (List.aspx):
<%@ Page Title="" Language="C#" MasterPageFile="~/Views/Shared/Global.Master" Inherits="System.Web.Mvc.ViewPage<IEnumerable<MyEntity>>" %> |
<asp:Content ID="Content1" ContentPlaceHolderID="TitleContent" runat="server"> |
</asp:Content> |
<asp:Content ID="Content2" ContentPlaceHolderID="MainContent" runat="server"> |
<%= Html.DisplayForModel("MyEntity")%> |
</asp:Content> |
<asp:Content ID="Content3" ContentPlaceHolderID="HeadContent" runat="server"> |
</asp:Content> |
Error appears when loading page:
Description: An unhandled exception occurred during the execution of the current web request. Please review the stack trace for more information about the error and where it originated in the code.
Exception Details: System.NotSupportedException: The specified type member 'AdditionalProperty' is not supported in LINQ to Entities. Only initializers, entity members, and entity navigation properties are supported.
Source Error:
Line 8: <% Html.Telerik().Grid(Model)
Line 9: .Name(gridModel.Name)
Line 10: .DataKeys(keys => keys.Add(c => c.Id))


When I have a custom property, I have to use ToList(), or it crashes. It cannot contain a property like
[ScaffoldColumn(false)]
public string _Mes
{
get
{
return CultureInfo.CurrentCulture.DateTimeFormat.GetMonthName(PRE_MES).Capitalize();
}
}
So, in the controller I have to use:
public ActionResult Admin()
{
return View(IIE.SIN_PROCESOENCUESTA.ToList());
}
The problem is, I think, I loose all Linq filtering capabilities. for small data tables, its ok.
Any ideas?

is there a way to tell the grid that it should ignore properties of the grid model which are not bound to specific columns? In my example the grid enumerates all properties of the DtoUserListEntry also the properties which are not bound.
@(Html.Telerik().Grid<
DeimosCore.DTO.DtoUserListEntry
>()
.Name("TelerikGrid")
.Localizable("de-DE")
.DataKeys(keys => keys.Add(o => o.BenutzerID))
.EnableCustomBinding(true)
.Columns(columns =>
{
columns.AutoGenerate(false);
columns.Bound(o => o.Kunde).Title("Kunde").Width(100);
columns.Bound(o => o.Benutzername).Title("Benutzername").Width(70);
columns.Bound(o => o.Vorname).Title("Vorname").Width(70);
columns.Bound(o => o.Nachname).Title("Nachname").Width(70);
columns.Bound(o => o.PLZ).Title("PLZ").Width(50);
columns.Bound(o => o.Ort).Title("Ort").Width(70);
columns.Bound(o => o.Strasse).Title("Straße").Width(100);
columns.Bound(o => o.Email).Title("E-Mail").Width(120);
columns.Bound(o => o.LastLogin).Title("Letzter Login").Width(100).Format("{0:dd-MM-yyyy HH:mm}");
columns.Bound(o => o.Status).Title("status").Width(30).Visible(false);
.... .... ....
Regards,
Benjamin

Thx

I managed to get it to work. Its a weird thing:
public partial class Company
{
database + domain properties
}
wont work with described errors above, while:
public partial class Company
{
database properties
}
public partial class Company
{
domain properties
}
will work perfectly. I am not yet sure why... well back to T4 to 'fix' generators

I have the following problem:
The class DtoUserListEntry (see below) is used for AjaxBinding Data to a Telerik Grid. Not all columns are used in the UI, but when the data is bound to the Grid all properties are read by some background Telerik Code. This is a bit annoying because we have a Validation Property (IsValid) which is not shown in the Grid but gets called for no reason. I tried your idea with seperating the properties to partial classes, but this didn't solve the issue.
public
class
DtoUserListEntry
{
public
int
KundeID {
get
;
set
; }
public
int
BenutzerID {
get
;
set
; }
public
string
Kunde {
get
;
set
; }
// b.Kunde.Name1,
public
string
Benutzername {
get
;
set
; }
// b.Login.FirstOrDefault<Login>().EMail,
public
string
Vorname {
get
;
set
; }
// b.Vorname,
public
string
Nachname {
get
;
set
; }
// b.Nachname,
public
int
? BenutzerAdresseID {
get
;
set
; }
public
string
Strasse {
get
;
set
; }
// b.BenutzerAdresse.Strasse,
public
string
PLZ {
get
;
set
; }
// b.BenutzerAdresse.PLZ,
public
string
Ort {
get
;
set
; }
// b.BenutzerAdresse.Ort,
public
string
Email {
get
;
set
; }
// b.BenutzerAdresse.Mail,
public
DateTime? LastLogin {
get
;
set
; }
// b.LastActivity,
public
int
? Status {
get
;
set
; }
public
bool
IsValid
{
get
{
return
Validate(); }
}
protected
bool
Validate()
{
// Do validation here!
return
true
;
}
}
Any suggestions?
Regards, Benjamin

Using AjaxBinding still breaks it for me also. Can you try server binding and see if my previous solution works for you, so we can narrow down the problem?
Best of luck :)
We will solve it, Iam sure of it :)
Rok

context.ContextOptions.LazyLoadingEnabled = false;
Hope it helps (partial classes still need to be separated)
Rok

Server Binding is no option for our solution.

But looking deeper at your source I see your problem is different then mine. The easiest workaround I see is to convert IsValid property to method, not a very nice solution I know. It might be possible to strip unwanted elements from IQueryable expression tree.
regards
Rok

The problem is that sometimes it is useful to have the "IsValid" property.
Is there a way to detect which way a property is called (via reflection or from which context)?

public
bool
IsValid
{ get; private set;
}
public void
Validate()
{
// Do validation here!
IsValid = true
;
}
Sure Validate() must be called if you want to see if object state is valid, but that is not that uncommon ;)

Did you ever come up with a solution?
Nick

I hope Telerik will fix this in future. In my eyes it makes more sence to call only the properties shown in the grid (defined by .Columns()) and not all properties the given model provides.

I fixed it by replacing the IQueryable<MyEntity> object with an List<MyEntity> object
=> in other words turning lazy loading into eager loading fixes this issue because the telerik grid is no longer responsible for reading the data out of the database and transforming it into entities...
hope this post can help other users and the telerik team will fix that issue

The default ordering is on the first column of the total set of columns, even if this column isn't shown on the screen.
When this column accidentaly is a non-database-backed property, you'll get the exception "The specified type member 'xxx' is not supported in LINQ to Entities. Only initializers, entity members, and entity navigation properties are supported.", because the grid will send the ORDER BY on this field to the database.
Hope this helps.
Edwin.

Some of my properties are not mapped in the DB and one of them was coincidentally the first in the Model Class, I just placed the "Id" property, that is mapped, on the top of the Model Class and it worked. I hope it works for whoever has a similar problem.