ansoesil’s blog

“Learning is experience. Everything else is just information.” – Albert Einstein

Performing Child Data Retrieval using Intersoft DataSource™

with 13 comments

Hello,

I promised several of our respondents to have a sample that demonstrate capability to retrieve child collection from parent object using Intersoft Data Source™. So I’ll try to elaborate it in this post in detail with step by step approach.

  • Sign up and download the Intersoft Data Source™ CTP release from here.
  • Follow the steps to create Astoria (ADO.NET Data Service) connection and set the service reference to your Silverlight Application Project. (Here is the link)
  • Don’t forget to add reference to ISNet.Silverlight, ISNet.SIlverlight.DataSource and System.Windows.Controls.Data.
  • Lets start by creating the UI first.

In this sample I’m going to use three data grids to show Customers – Orders – Orders Details relationship. So the first Grid will show the list of Customers, the second Grid will show the Orders from selected customer in the Customers Data Grid, and the third Grid will show the Order Details from selected order in Orders Data Grid.

parentchildren1

  • Insert the Astoria Data Source and configure its settings.

parentchildren2

  • Since I want my grid to retrieve the child data when ever i select a row in the grid, I’m going to hook the SelectionChanged event in Customers Grid and Orders Grid

parentchildren3

  • Next we need to attached Selecting and Selected Event Handler in Astoria Data Source, so that we can control the data retrieval process later on.

parentchildren4

  • Everything is set, and now lets go to the code behind.
  • First of all we want the Application to load the data directly when application is loaded, therefore we need to call AstoriaDataSource1.Select(“Customers”) when the application is ready.

parentchildren5

  • Remember that we attached SelectionChanged event for Customers Grid and Orders Grid? Lets put some action into it.
    So we will retrieve Orders when an item in Customers Grid is selected, and we will retrieve Orders Details when an item in Orders Grid is selected.

parentchildren6

  • Now is the important part. When we call AstoriaDataSource1.Select(“Orders”) in CustomersGrid_SelectionChanged, we want it only to retrieve the Orders from selected item (Customer with specific CustomerID). So how can we handle this?
    Currently you need to handle it at Astoria Data Source’s Selecting Event Handler as follows.

parentchildren7

When you call AstoriaDataSource1.Select(“Orders”), it will asked the AstoriaDataSource to perform data retrieval process. You can interupt the process at two points which are at the beginning (Selecting) and at the ending (Selected). Since we want the AstoriaDataSource to select only Orders of current selected Customer, we need to provide advance query during Selecting event.

Customers customer = CustomersGrid.SelectedItem as Customers;

var query = from c in context.CreateQuery<Customers>(“Customers”).Expand(“Orders”)
where c.CustomerID == customer.CustomerID
select c;

DataServiceQuery<Customers> serviceQuery = query as DataServiceQuery<Customers>;
e.DataServiceQuery = serviceQuery;

By providing e.DataServiceQuery with an advanced query like this, the Astoria Data Source will compile it and send it to Astoria Data Service.

  • Lastly what you need to do is to handle the action when the data is retrieved at the Selected Event.

parentchildren8

Since Astoria sends the data back as collection of EntityDescriptor, we need to do additional Linq query to get the object collection correctly.

In the query i also put additional checking c.Entity.GetType() == typeof(Orders) is to filter out parent data when we’re doing child data retrieval.

parentchildren9

parentchildren101

  • And we’re done. Run your application and you’ll get something like this.

parentchildren11

parentchildren12

Regards
Andry

Sample Link

Written by ansoesil

February 6, 2009 at 6:14 am

13 Responses

Subscribe to comments with RSS.

  1. Andry, I’m glad I asked for this sample, and I’m super glad you made it. I’ll be honest with you, if you had not provided this sample to provide the steps or at least a view of approaching it, I would have not been able to do this without help.

    So what does it mean?
    a) I should have known Astoria better, it’s because that’s how you program against Astoria, even using your DS?
    b) or We just need some of your expertise to highlight the features in your DS?
    c) Or I should be selling newspaper on the street…? 🙂

    Well, looks like I need to get my hands dirty and start getting deeper until we get the next drop.
    I’ll be examining some other scenarios and keep you posted.

    Andry, let me ask you a few questions.

    a) Let’s suppose I create a similar application I’m at Customer ABC and the user clicks a button and they can view the orders in a PopUp window that I chose to create to show orders. So now my customer grid is pointing at Customer ABC and my popup window is showing Orders of Customer ABC. Suddenly, the user gets a phone call to look up the orders of customer CBS.
    If she moves to customer CBS on that same original customer grid and presses the button again, she will get another window showing the orders of customer CBS, but my question is: Are we going to loose the first buffer for orders of customer ABC? or will we get a separate collection buffer one for ABC and one for CBS?

    b) How long these collection will stay around? Or I should ask, what will notify GC that the child collections are no longer in use? How long can I depend on them being around, in case in code I need to reference some of the data of child collections?

    c) Another scenario that comes to mind is different that what you did. You loaded each order on demand as it was needed (lazy loading), which is fine. But let’s say I need to get a total of orders for all customers for zip code 12345. This means when I get a customer for zip code 12345, I need to get it’s orders and detail of each orders to calculate total sales (from order detail) right away without the need of manually doing round trip access back to the service. I need the service to get me Customer 1 with it’s orders and all the details at one shot, send it to me before moving to next customer. This a situations that I had previously run into and it’s very common. Your input will be very valuable!

    Thank you Andry for taking the time for these Blogs.
    ..Ben

    Ben Hayat

    February 6, 2009 at 10:30 pm

  2. Hi Ben

    Thanks for your input too 🙂

    I think the answer to all of these questions are actually Data Caching concept that our team currently working on but that for later.

    I’ll elaborate your question without this concept first.

    a) When you request the Order for Customer ABC, you will have a round trip to the data service and it will return you the data. This is in separate collection, it has no relation to your customer data that currently reside in the Data Grid.

    Thats why i think Astoria developer decide to gives the Customer (parent) object when i do “Expand”.

    In your scenario you mentioned that you have pop up window that display the Order data, i assume you attached the data to that pop up window. So since each order data that we retrieved is a separate collection. Each of them will still alive until the host “Pop Up” window is destroyed, and then the GC will pick it up.

    b)
    As far as I know the GC runs periodically, and it will clean up any object that don’t hold any references.
    So if you only attached the child data in the Pop Up window, it will only be around until the pop up window is gone.
    If you want to keep the child data (Orders), you can add the reference to Customer.Orders collection when you get the data. And the next time you want to show it again, you don’t need another round trip to server.
    But in this case, the data will stay until you remove the Customers collection from the Data Grid or when the Data Grid is destroyed.

    c)
    Hmm so you want both Orders and OrderDetails directly.
    I don’t have the resource right now, since I’m at home. But in astoria you can do this, in the query string you can do something like:

    /Customers(‘ALFKI’)?$expand=Orders/Order_Details

    which means it will get Customer “ALFKI” and all the Orders related to it and the Order_Details that related to Orders.

    But i’m not sure yet how the query looks like since i can’t test it. But probably you can try

    var query = from c in context.CreateQuery(”Customers”).Expand(”Orders”).Expand(“Order_Details”)
    where c.ZipCode == “12345”
    select c;

    About the data caching concept that i mentioned before, basically it will address a situation like this.

    You have lists of Customers, then you open Order for Customer ABC (at this point we need a round trip to get the data).

    What the caching mechanism will do (if enabled) is that we keep this this data in a key pair, so that if you try to get the same data with the same key, you won’t have another round trip again.

    So with this caching concept, you can control which data that need to be kept, you can invalidate the cache if necessary and so on.

    Another important thing that we going to enable in the caching concept is level of caching (it can be global through out the application, can be per individual data source control, can be per page, and so on) we still carefully design this.

    But the idea is that in an application most of the time we’re dealing with the same data over and over, having some data cached through out the application can be quite useful 🙂

    Hope this make sense
    Don’t worry I’ll cover this when the feature is ready, probably it will be more clearer later 🙂

    Regards

    Andry

    ansoesil

    February 7, 2009 at 9:45 am

  3. Hi Andry;

    >>Hope this make sense
    Don’t worry I’ll cover this when the feature is ready, probably it will be more clearer later :)<<

    Crystal clear! So, it seems like you’re creating a dictionary of these collections that you want to cache by giving it a key and having a reference to collection, this way you won’t let GC to take it away from you and these collections (which each basically represent one data record) can stick around as long as we wanted them or as soon as we remove them from dictionary, GC deletes the collections with no reference.
    Sounds great!

    Now that you got me going, let’s get deeper… It would be nice to be able to take advantage of isolated storage to be able to store some of these collections and the data source should be able to use isolated storage as well.
    This way, we know there are some data that don’t change that often or hardly ever, but are used internally by apps, for example zip codes, or certain product’s engineering specs for manufacturing that I save in IS for the first time, and from then on, I can use it from user’s machine. [I think you should consider this option for your design and you’ll soon find out why I say this :-)].

    Now I wasn’t talking about offline, but we’ll talk about that after MIX 🙂

    Andry, in my 30 years of IT experience, I’ve seen so many definitions of the word “Data Source”, that I have lost count. I’m not sure if I remember your detail definition of what you call a “Data Source”. Could you please give a technical definition how you see it with your product?
    I’d like to see if you mean the same as DataSet or what?

    Sorry for bothering you on Sat. but I enjoy delving into new developments and designs.
    Did you get my email Link to Jamie Cool presentation?

    Ben Hayat

    February 7, 2009 at 10:49 am

  4. Yup we have discussion about this isolated in earlier meeting with my team, and also about the offline working thing so yea its going to be interesting 🙂

    Haha true, the word “data source” is somewhat general.
    In our perspective, i would say data source is any collection of data object. Which can be in many form.

    In a way DataSet can be called as “data source” as well, it contains collection of data but in Tabular object.
    Lately in the application development we often see Business Object, and the data source are in form of collection of this Business Object.

    Intersoft Data Source has three data source control atm, each of them targeting different approach.
    1. XML (if we extract it, we got a collection of xml node which can later be translate to business object. so here we got a collection of data object)
    2. WCF , its connect to wcf service where user can provide us with IEnumerable kind of object. IEnumerable means a collection of data object)
    3. Astoria, its connect to astoria service. The service return collection EntityDescriptor object, again another collection of data.

    So that is my understanding of the word data source 🙂

    PS: Yup i got the mail, thanks a lot. will see it soon got something to do in this weekend 🙂
    Have a nice weekend

    ansoesil

    February 7, 2009 at 11:27 am

  5. Andry, as I’m getting closer to start using the Data Source, what and where would be the proper place to post my questions or report bug or errors?

    Thanks!
    ..Ben

    Ben Hayat

    February 8, 2009 at 12:17 am

  6. Andry, a none related question to this post. How is a) Paging is accomplished with your system. For example be able to show 10 rows of data for each page. Is this in DS or presenter manager.

    b) Filtering – same as above

    c) Grouping – same as above

    In case of SL, is it usually the UI component’s responsibility to to the above or the DS?

    Thanks!

    Ben Hayat

    February 8, 2009 at 1:34 am

  7. Hi Ben, you can send the emails to technical@intersoftpt.com or directly to me.

    Paging and Filtering is the capability in the data source control. You can supply this information as DataSourceSelect Arguments

    In this picture
    https://ansoesil.files.wordpress.com/2009/02/crudoperation5.png?w=700&h=330

    I used the DataSourceSelectArguments to select top 50 rows (“TotalRowCount”) . To do paging what you need to do is add additional info which called “Skip” = 10 (for example), so it will skip first 10 rows and grab 50 rows.

    Same goes for Filter, you need to supply Filter Expression to DataSourceSelectArguments

    However if you use Intersoft Presenter(tm) you don’t need to do it manually, everything is taken care by Intersoft Presenter 🙂

    For Grouping, its the capability inside Intersoft Presenter. The data source don’t have this capability. But you can always perform Linq grouping when the data is retrieved (Selected Event)

    So in conclusion you can say that the UI need to provide info to data source control, and then data source control will asked to its source based on the information provided by the UI.

    Regards
    Andry

    ansoesil

    February 8, 2009 at 8:48 am

  8. Hi Andry;

    Since I had looked at many codes, I kind of didn’t pay attention to it’s detail on being able to set the args for the select. Very nice!

    Of course I’m going to use the presenter. In fact by March time of your DS release, if presenter is in good shape, I’ll take that one too. 🙂

    I hope I don’t sound too demanding, but I’m sure all these samples you’re making will come into good use. How about a sample that shows most of the common events of the DS. My next thoughts were on how can I check data before leaving DS or how can I check data coming from DS or when we get errors from DS.

    Q: When we receive a collection of data from Astoria and now it’s at the client, can I then create new sub collections using LINQ against that original collection that is at client side? For example, I get all the customers for State of Florida from Astoria, and now I can create one query for zip code 33313 or another query for customers with low sales and etc. And then use these sub queries to show to end user? If yes, taking it one step further, could I then attach them to DS so, if any changes are made to these sub queries, the changes can become persistent to database or for the case of change I have to get the sub query directly from Astoria?

    Thank you as always!
    ..Ben

    Ben Hayat

    February 8, 2009 at 10:01 pm

  9. Hi Ben

    **
    My next thoughts were on how can I check data before leaving DS or how can I check data coming from DS or when we get errors from DS.
    **

    Sure I’ll post something about this later.

    **
    When we receive a collection of data from Astoria and now it’s at the client, can I then create new sub collections using LINQ against that original collection that is at client side?
    **

    Yup you can do it at or after Selected Event, where you have the data.

    Do the query there, and if you use Intersoft Presenter, you can attached it again to DataSource through the EventArguments

    private virtual void AstoriaDataSourceView_Selected(object sender, DataSourceEventArgs e)
    {
    AstoriaDataSourceStatusEventArgs args = e as AstoriaDataSourceStatusEventArgs;

    args.ReturnValue = [your query / collection]

    }

    if you use standard controls, you can just assign the query back to your UI control.

    **
    if any changes are made to these sub queries, the changes can become persistent to database or for the case of change I have to get the sub query directly from Astoria?
    **

    Hmm i don’t quite get the question here. If you perform additional query / sub query at the selected event , basically you interupting the process so that the UI can give the data that you expected. But thats about it, the data in data base will remain the same.

    Regards
    Andry

    ansoesil

    February 9, 2009 at 10:28 am

  10. >>Hmm i don’t quite get the question here. If you perform additional query / sub query at the selected event , basically you interupting the process so that the UI can give the data that you expected. But thats about it, the data in data base will remain the same.<<

    Let me bring up the sample again and see if I can describe it better.
    Suppose I do a query of customers and I get 1000 customers at client side. If I for example edit or delete any of these customers from this query, I can have your DS and Astoria to save the edit or delete back. No problem here.
    Now, suppose I do a new query on the client side and I get 5 records that are in zip code 33134.
    Now, if I edit any of these five that are in new query, can I still save those 5 records back like I could with the first query?
    My question was triggered, because Astoria has no knowledge of the second query, I wonder if it can maintain the changes made to those 5. So, I may have to do a second query again from Astoria to get those 5, but I’m trying to avoid another trip.
    Do I make sense?
    ..Ben

    Ben Hayat

    February 10, 2009 at 1:04 am

  11. Hi Ben

    Ah i get it now. Pretty sure it can be done, since when you query using LINQ, it provides a sub set collection that have references to the original one, so if you change the sub set , the original one will reflected as well.

    One thing should be noted, that if you want to achieve this with presenter later on, you need to enable all client side process, for filtering, sorting, etc so that the master data is not changed.

    The default mode currently is always requesting data from Data Source Control by providing the filter expression, sort expression and so on. But we also have the client side processing using LINQ (like what we do for unbound mode and xml data) that can be enabled later on (this feature not available in February 09 CTP)

    Regards
    Andry

    ansoesil

    February 10, 2009 at 9:45 am

  12. Yes, you got my point. Thanks for the confirmation. Looks like this baby can do a lot. 🙂

    Ben Hayat

    February 10, 2009 at 10:32 am

  13. […] Performing Child Data Retrieval using Intersoft DataSource™ […]


Leave a comment