Silverlight RIA query with client-side filtering

1.7k views Asked by At

I have the following query that returns empty (enumeration yielded no results):

CurrentStudent = _ctx.Students.SingleOrDefault();
var qry = _ctx.GetStudentsWithAdultContactsQuery(); 
_ctx.Load(qry.Where(s => s.StudentID == studentId));
dataForm1.CurrentItem = CurrentStudent;
BeginEdit();

Instead, I have to do the following, as if I were working with a regular SL WCF Service:

var qry = _ctx.GetStudentByIDQuery(studentId);
var load = _ctx.Load(qry);
load.Completed += (s, e) =>
{
    CurrentStudent = _ctx.Students.FirstOrDefault();
    dataForm1.CurrentItem = CurrentStudent;
    BeginEdit();
};

Why does the first method not work? The server-side query does the same filtering by ID as the first, so it's not the query itself. None of the examples of using RIA that I've seen use the Completed event handler; RIA is supposed to handle the asynchronous loading behind the scenes. What gives?

EDIT I wanted to refocus the question a bit. Here's another query that I have that works just as you would expect:

var query = ctx.GetStudentsWithAdultContactsQuery();
studentDataGrid.ItemsSource = ctx.Students;
ctx.Load(query);

I am not explicitly handling the Completed callback here, and that's how I see RIA used in examples on the web, including here. So, the obvious differences between this query and the one that doesn't work is (a) the filtering and (b) the databinding target. But why should either make a difference?

1

There are 1 answers

0
Antony On BEST ANSWER

I think I've worked out an answer:

The two situations -- binding a grid and binding a dataform -- are different because in the former scenario I am binding to an EntitySet (Students) while in the case of the dataform I am binding to an individual entity (Student). Well, duh! But so what?

So, an EntitySet implements INotifyCollectionChanged, which raises a notification event when entities are added to the set (as when the query returns with the results), causing the grid to update. The dataform CurrentItem, on the other hand, is not binding to an EntitySet, so it's not listening to changes in the Students collection and doesn't know when CurrentStudent is no longer null. Hence, I have to wait for the load to complete, or I can do something that the grid presumably does, and listen to the Students collection, which works to the same effect:

var qry = _ctx.GetStudentsWithAdultContactsQuery().Where(s => s.StudentID == studentId);
_ctx.Load(qry);
_ctx.Students.EntityAdded += new EventHandler<EntityCollectionChangedEventArgs<Student>>(Students_EntityAdded);
//...
void Students_EntityAdded(object sender, EntityCollectionChangedEventArgs<Student> e)
{
    dataForm1.CurrentItem = e.Entity;
}

Or, more succinctly:

var qry = _ctx.GetStudentsWithAdultContactsQuery();
_ctx.Load(qry.Where(s => s.StudentID == studentId));
_ctx.Students.EntityAdded += (s, e) => {
    dataForm1.CurrentItem = e.Entity;
};

I'm marking the question as answered, but please feel welcome to post your explanation if it differs from mine; I will happily vote it up if it offers new insight.