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

Work with partial class properties

19 Answers 442 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.
Roy Wang
Top achievements
Rank 1
Roy Wang asked on 25 Feb 2010, 08:23 AM
Hi,

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

Sort by
0
Atanas Korchev
Telerik team
answered on 25 Feb 2010, 09:26 AM
Hi Roy Wang,

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.
0
Donatas B
Top achievements
Rank 1
answered on 19 Jun 2010, 11:37 AM

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))



0
Donatas B
Top achievements
Rank 1
answered on 22 Jun 2010, 06:54 AM
Oh, it seems Grid crashes when Ajax is enabled.
0
Jorge
Top achievements
Rank 2
answered on 24 Nov 2010, 05:48 AM
Same problem here... but with version Q3.

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?

 

 

 

 

0
Benjamin
Top achievements
Rank 1
answered on 31 Jan 2011, 03:54 PM
Hello,

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
0
Rok
Top achievements
Rank 2
answered on 31 Jan 2011, 07:11 PM
Same question as Benjamin.

Thx
0
Rok
Top achievements
Rank 2
answered on 02 Feb 2011, 10:09 AM
Hi Benjamin

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


0
Benjamin
Top achievements
Rank 1
answered on 03 Feb 2011, 12:13 PM
Hi Rok, thanks for your reply! I'm sorry to say, but your solution doesn't work for me :-(

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
0
Rok
Top achievements
Rank 2
answered on 03 Feb 2011, 01:24 PM
Hi,

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
0
Rok
Top achievements
Rank 2
answered on 03 Feb 2011, 02:08 PM
I managed to get it to work with AjaxBiniding also. Just disable lazy loading for those requests.

 context.ContextOptions.LazyLoadingEnabled = false;

Hope it helps (partial classes still need to be separated)

Rok

 

 

 

 

0
Benjamin
Top achievements
Rank 1
answered on 03 Feb 2011, 04:27 PM
In my case the object is not an entity framework object but a POCO. So disabling lazy loading won't help. Is there no way to prevent the Telerik Grid from reading all properties?

Server Binding is no option for our solution.
0
Rok
Top achievements
Rank 2
answered on 03 Feb 2011, 05:09 PM
Mine are Entity POCO objects and the error I was fighting was "System.NotSupportedException: The specified type member 'AdditionalProperty' is not supported in LINQ to Entities. Only initializers, entity members, and entity navigation properties are supported."

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
0
Benjamin
Top achievements
Rank 1
answered on 03 Feb 2011, 05:18 PM
Yes, you're right. I also thought that making "IsValid" a method might be a solution, but then I can go back and program Java ;-)
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)?
0
Rok
Top achievements
Rank 2
answered on 03 Feb 2011, 06:30 PM
How about something like this:

 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 ;)
0
Nick
Top achievements
Rank 1
answered on 22 Jun 2011, 11:39 AM
I am receiving the exact same error and haven't been able to fix this despite trying everything in this thread.

Did you ever come up with a solution?

Nick
0
Benjamin
Top achievements
Rank 1
answered on 24 Jun 2011, 08:34 AM
We solved the problem by creating a plain model class which only contains the properties shown in the grid (without validation). That's not the nicest solution but we haven't found a way to prevent the grid from reading all properties.

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.
0
Da_Wolf
Top achievements
Rank 1
answered on 12 Oct 2011, 01:23 PM
Hey I know, it's an old topic but I was also experiencing the same problem today (using the newest telerik mvc release).

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
0
Edwin
Top achievements
Rank 1
answered on 13 Feb 2013, 11:27 AM
I had the same problem and figured out what went wrong:

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.
0
William
Top achievements
Rank 2
answered on 04 Mar 2013, 11:52 PM
I had a similar problem and the suggestion Edwin said worked for me.

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. 
Tags
Grid
Asked by
Roy Wang
Top achievements
Rank 1
Answers by
Atanas Korchev
Telerik team
Donatas B
Top achievements
Rank 1
Jorge
Top achievements
Rank 2
Benjamin
Top achievements
Rank 1
Rok
Top achievements
Rank 2
Nick
Top achievements
Rank 1
Da_Wolf
Top achievements
Rank 1
Edwin
Top achievements
Rank 1
William
Top achievements
Rank 2
Share this question
or