locked
Why does the default query fire again after a more specific query? RRS feed

  • Question

  • I thought I was being clever with the following WCF RIA Services code, avoiding the ToList() call until my more specific query to keep my code performant. (If I use it in the default query it will force every record to be retrieved on every query.)

    When my data grid executes its GetPersonByName() query all of the "John"s appear (or whoever), with a nice read-only label listing their Pets (editable in a separate grid) - but only for a split second. A moment later, the Pet label is cleared. I set breakpoints and determined that *after* GetPersonByName() is called and my data grid is updated correctly, GetAllPeople() fires once more, and wipes out the work I did in the specific query.

    Is there a reason for this? And here I thought I had a very good method of keeping my code performant. (In production the table names would be different and there would be ample data, this is merely for example.)

    [Query(IsDefault = true)]
    public IQueryable<RiaPerson> GetAllPeople() {
    	var results = from p in ObjectContext.People
    				  select new RiaPerson
    					  {
    						  Id = p.Id,
    						  Name = p.Name,
    						  _pets = p.Person_Pet.Select(pP => pP.Pet),
    						  Pets = "",
    					  };
    	return results;
    }
    
    public IQueryable<RiaPerson> GetPersonByName(string? Name) {
    	var people = GetAllPeople().Where(p => p.Name == Name).ToList();
    	foreach (var p in people) {
    		p.Pets = String.Join(", ", p.pets.Select(p => p.Name));
    	}
    	return people.AsQueryable();
    }

    The classes are simple, with a many-to-many table:

    public class RiaPerson
    {
    	[Key]
    	public int Id { get; set; }
    
    	public string Name { get; set; }
    
    	internal IEnumerable<RiaPet> _pets;
    	public string Pets { get; set; }
    
    	[Include]
    	[Association("RiaPerson_RiaPet_RiaPerson", "Id", "PersonId", IsForeignKey = false)]
    	public IEnumerable<RiaPerson_RiaPet> People_Pets { get; set; }
    }
    
    public class RiaPet
    {
    	[Key]
    	public int Id { get; set; }
    
    	public string Name { get; set; }
    
    	[Include]
    	[Association("RiaPerson_RiaPet_RiaPet", "Id", "PetId", IsForeignKey = false)]
    	public IEnumerable<RiaPerson_RiaPet> People_Pets { get; set; }
    }
    
    public class RiaPerson_RiaPet
    {
    	[Key]
    	public int PersonId { get; set; }
    	[Key]
    	public int PetId { get; set; }
    
    	[Include]
    	[Association("RiaPerson_RiaPet_Person", "PersonId", "Id", IsForeignKey = true)]
    	public RiaPerson Person { get; set; }
    
    	[Include]
    	[Association("RiaPerson_RiaPet_Pet", "PetId", "Id", IsForeignKey = true)]
    	public RiaPe Pet { get; set; }
    }


    Wednesday, April 3, 2013 6:00 PM

Answers

  • Thanks for the assist Yann! Your reassurance let me pick this one apart.

    I solved it. I had a couple queries of the main/default one in my code (DataWorkspace.WCF_RIA_Services.RiaPeople in my example, or RiaPersons, whatever). I didn't realize these queries directly on the DataWorkspace would affect the data grid. I changed them to use the specific query (DataWorkspace.WCF_RIA_Services.GetPersonByName in example), except with null parameters. Now all is well!


    Wednesday, April 3, 2013 8:05 PM

All replies

  • Queries are supposed to be "composable", in that you can build levels of queries on queries & only the final expression tree gets pushed down to the data provider. And as far as I've seen, that's how it works. But there's a couple of things that can waylay that path.

    The first is to not use ToList in the intermediate levels (as you already mentioned). Another is to use IEnumerable<TEntity>, instead of IQueryable<TEntity> in those layers. I just read something recently saying that using IQueryable<TEntity> will force the production of records before you want.


    Yann - LightSwitch Central
    Luminous Tools for LightSwitch (a FREE productivity extension)
    FREE Themes, Controls, Types and Commands
     
    Please click "Mark as Answer", if any reply answers your question.
    Please click "Vote as Helpful", if you find any reply helpful.
     
    By doing this you'll help others to find answers faster.

    Wednesday, April 3, 2013 6:22 PM
    Moderator
  • Thanks for the assist Yann! Your reassurance let me pick this one apart.

    I solved it. I had a couple queries of the main/default one in my code (DataWorkspace.WCF_RIA_Services.RiaPeople in my example, or RiaPersons, whatever). I didn't realize these queries directly on the DataWorkspace would affect the data grid. I changed them to use the specific query (DataWorkspace.WCF_RIA_Services.GetPersonByName in example), except with null parameters. Now all is well!


    Wednesday, April 3, 2013 8:05 PM