none
What is the best way for populating controls using LINQ? RRS feed

  • Question



  • Let's say I have a datagrid (WPF datagrid, but the problem is not related to the specific control) and I want to display my data.

    Suppose I have two LINQ classes, Company and Contact. Contact class has a Company field, because every contact has a company. It's a simple 1 to many relationship.

    Now, I do my query:

    var q=from c in db.Contacts
    select c;
    

    and use it to populate my datagrid (but whatever control should be the same i guess).

    In the datagrid columns, I create one like this:

    <my:DataGridTextColumn Binding="{Binding Path=Company.Name}" Header="Company Name" Width="100" IsReadOnly="True" />
                            
    
    Everything works fine and my datagrid displays the company name for every contact.

    But there is a problem. The drawback for using the "Company.Name" binding path is that for every record in the datagrid, LINQ does an additional query for retrieving data from the related Contact's Company. This become very annoying while scrolling the datagrid: if DataContext.Log is on Console.Out, you can see the queries being called repeatedly.

    Of course this is not good. So my first thought was to come back to my LINQ query for datagrid binding and select all fields i need directly.Something like:

    var q=from c in db.Contacts
    select new{c.Company.Name};
    


    This works but here it comes another problem. 
    If I want to access the SelectedItem property of the datagrid, I can't cast anymore the object. Infact, with the first query, a simple:

    Contact c=(Contact)datagrid.SelectedItem;
    

    was fine, but now, since I'm passing an anonymous type to the datagrid, I can't do this.

    Now, the main question is: what is the right approach? I know I can cast anonymous types with a trick, but I don't think that's how things should be done... Neither should be normal to perform queries during datagrid scrolling, of course

    Any wise suggestion? Thank you very much

    PS: I think it's a very common issue...
    PPS: I know WPF datagrid is not supported yet but the problem comes with any other control, even if in my case I was using the datagrid. 
    Monday, March 8, 2010 9:52 PM

Answers

  • Hi,

    Perhaps, eager loading would be the right approach in this case. So when you are pulling Contacts, you need to prefetch the associated Company record in the same query like this:

    var dc = new YourDataContext();
    var options = new DataLoadOptions();
    options.LoadWith<Contact>(c => c.Company);
    dc.LoadOptions = options;
    
    var query = 
      from c in dc.Contacts
      select c;
    
    //bind query to datagrid...


    Hope that helps.

    Regards,

    Syed Mehroz Alam
    My Blog | My Articles
    • Marked as answer by Radox Tuesday, March 9, 2010 11:03 AM
    Tuesday, March 9, 2010 8:56 AM

All replies

  • Hi,

    Perhaps, eager loading would be the right approach in this case. So when you are pulling Contacts, you need to prefetch the associated Company record in the same query like this:

    var dc = new YourDataContext();
    var options = new DataLoadOptions();
    options.LoadWith<Contact>(c => c.Company);
    dc.LoadOptions = options;
    
    var query = 
      from c in dc.Contacts
      select c;
    
    //bind query to datagrid...


    Hope that helps.

    Regards,

    Syed Mehroz Alam
    My Blog | My Articles
    • Marked as answer by Radox Tuesday, March 9, 2010 11:03 AM
    Tuesday, March 9, 2010 8:56 AM
  • Thank you very much, it solved my problem!
    Tuesday, March 9, 2010 11:05 AM