Issue with LINQ contains

4 posts, 2 answers
  1. Art Kedzierski
    Art Kedzierski avatar
    107 posts
    Member since:
    Nov 2009

    Posted 29 Jan 2013 Link to this post

    I'm having issues filtering an OpenAccess model with LINQ. Here's the scenario: I'm generating an array of IDs from the selected items of a RadGrid that I want to use to filter the EntitiesModel:

    public ArrayList GetTelerikGridSelections(Telerik.Web.UI.RadGrid grid)
    {
        ArrayList selectedItems = new ArrayList();
        if (grid.MasterTableView.DataKeyNames.Length > 0)
        {
            string key = grid.MasterTableView.DataKeyNames[0];
            for (int i = 0; i < grid.SelectedItems.Count; i++)
            {
                selectedItems.Add((int)grid.MasterTableView.DataKeyValues[grid.SelectedItems[i].ItemIndex][key]);
            }
        }
     
     
        using (GlobalLabManager.GLMEntitiesModel ctx = new GlobalLabManager.GLMEntitiesModel())
        {
            var q = from i in ctx.Reservations
                    where selectedItems.Contains(i.ResourceFK)
                    select i;
            schd_Resources.DataSource = q;
            schd_Resources.Rebind();
        }
    }

    However, I get the following error when I run the code. No mention of it in any of my searches.

    An exception occured during the execution of 'Extent<GlobalLabManager.Reservation>().Where(r => value(Schedule+<>c__DisplayClass0).selectedItems.Contains(Convert(r.ResourceFK)))'. Failure: Execution of 'System.Collections.ArrayList:Contains(Object)' on the database server side currently not implemented.
    See InnerException for more details.
    Complete Expression:
    .Call System.Linq.Queryable.Where(
        .Constant<Telerik.OpenAccess.Query.ExtentQueryImpl`1[GlobalLabManager.Reservation]>(Extent<GlobalLabManager.Reservation>()),
        '(.Lambda #Lambda1<System.Func`2[GlobalLabManager.Reservation,System.Boolean]>))
     
    .Lambda #Lambda1<System.Func`2[GlobalLabManager.Reservation,System.Boolean]>(GlobalLabManager.Reservation $r) {
        .Call (.Constant<Schedule+<>c__DisplayClass0>(Schedule+<>c__DisplayClass0).selectedItems).Contains((System.Object)$r.ResourceFK)

    Anyone else seen this error before? Or have a better idea how to accomplish what I'm looking for?
  2. Answer
    Viktor Zhivkov
    Admin
    Viktor Zhivkov avatar
    291 posts

    Posted 30 Jan 2013 Link to this post

    Hello Art,

    The exceptions is caused by the fact that you have used weakly typed ArrayList in the LINQ query instead of a more strongly typed generic collection.
    If you know the type of the item keys you should use the proper generic type - for example:
    1.List<int> selectedITems = new List<int>();
    2....
    3.selectedItems.Add((int)grid.MasterTableView.DataKeyValues[grid.SelectedItems[i].ItemIndex][key]);
    4....
    5.var q = from i in ctx.Reservations
    6.      where selectedItems.Contains(i.ResourceFK)
    7.      select i;

    That way your LINQ query will work as expected. Please keep in mind that the type of the i.ResourceFK should match the type of the items in the selectedItems collection.
    In general the usage of System.ArrayList type is considered bad practice after the introduction of generics and should be avoided.

    Greetings,
    Viktor Zhivkov
    the Telerik team
    Q3'12 SP1 of OpenAccess ORM packs Multi-Table Entities mapping support. Check it out.
  3. DevCraft banner
  4. Art Kedzierski
    Art Kedzierski avatar
    107 posts
    Member since:
    Nov 2009

    Posted 30 Jan 2013 Link to this post

    That fixed that issue (thanks!), but I'm still having a hard time figuring out the correct way to filter the OpenAccessLinqDataSource. I see how to set up a filter based on a single parameter (WHERE EQUALS, etc), but I don't see how to do something equivalent to a SQL 'WHERE IN' clause. Now that I have a properly cast List<int> of IDs from a control (in this case a RadGrid) I need to filter the incoming appointments of a RadScheduler, limiting the SELECT results. If I were writing SQL, It would be something like:  

    SELECT * FROM [Reservations] WHERE [ResourceFK] IN (<List of selected IDs from RadGrid>)

    Is this even possible with an OpenAccessLinqDataSource, or should I be looking at a different data source type?
  5. Answer
    Doroteya
    Admin
    Doroteya avatar
    502 posts

    Posted 04 Feb 2013 Link to this post

    Hello Art,

    In order to filter the result set in the way you need, I suggest you to use the Selecting event of the OpenAccessLinqDataSource. The following snippet demonstrates the approach:
    protected void OpenAccessLinqDataSource2_Selecting(object sender, Telerik.OpenAccess.Web.OpenAccessLinqDataSourceSelectEventArgs e)
    {
      //... Assign the value of the selectedItems list here ... 
      using (EntitiesModel ctx = new EntitiesModel())
      {
        e.Result = ctx.Reservations.Where(r => selectedItems.Contains(r.ResourceFK).ToList();
      }
    }

    The basic idea is that since the Selecting event occurs before the data-retrieval you could attach a custom filtering expression to the result. You can find details about how the solution works in the second part of this documentation article (How to: Change the Filter Expression Runtime).

    Note that in real live scenarios we recommend the following ways to manage the OpenAccessContext:
    - Using a master page
    - Using a custom Http Module
    - Using an Http Context

    I hope that works for you. If you have any additional questions, do not hesitate to get back to us.

     

    Kind regards,
    Doroteya
    the Telerik team
    Q3'12 SP1 of OpenAccess ORM packs Multi-Table Entities mapping support. Check it out.
Back to Top