(X) Hide this
    • Login
    • Join
      • Generate New Image
        By clicking 'Register' you accept the terms of use .

WCF RIA Services Part 2: Querying Data

(15 votes)
Brian Noyes
>
Brian Noyes
Joined Jun 10, 2010
Articles:   19
Comments:   117
More Articles
65 comments   /   posted on Jun 24, 2010
Categories:   Data Access , Line-of-Business

This article is Part 2 of the series WCF RIA Services.

Overview

In Part 1, I introduced the basics of WCF RIA Services and walked you through the “hello world” equivalent for WCF RIA Services. That may have all seemed too simple, and you can’t really drag and drop your way to real world applications. For real applications, you are going to need to know more how to customize what services are exposed to the client and how to consume them on the client side. In this article, I’m going to drill down a little deeper into the process of querying data from the client. I’ll cover the conventions for query methods that you define on your domain service, as well as how to do it with configuration (attributes) instead of based on convention. I’ll show some of the programmatic ways that you can perform the queries on the client side. Finally,  I’ll talk about using data from sources other than Entity Framework.

The starting point for this article is the solution that resulted from the steps in Part 1, which you can download here.

The finished code for this article can be downloaded here.

Step 1: Add a parameterized collection query to your domain service

In the last article, I walked you through creating a domain service and after you completed the wizard, a single query method had been added to the domain service class that looked like this:

 public IQueryable<Task> GetTasks()
 {
     return this.ObjectContext.Tasks;
 }

That query method just returned all of the tasks in the database as an IQueryable<T> and took no arguments. If you want to have more specific queries available to the client without returning all the rows, you can add specific query methods to the domain service, and they will be code generated on the client side as well. You can also choose to return an IEnumerable<T>, but if the underlying provider (i.e. Entity Framework or LINQ to SQL) returns IQueryable<T>, they you should pass that through instead as it supports more scenarios.

Say that a common use case for your application was to allow the user to retrieve tasks for a given date range. They could search for tasks before a given start date or after or between. To support that, add the following query method to your domain service:

 public IQueryable<Task> GetTasksByStartDate(
     DateTime lowerDateTimeInclusive, 
     DateTime upperDateTimeInclusive)
 {
     return this.ObjectContext.Tasks.Where(
         t => t.StartDate >= lowerDateTimeInclusive && t.StartDate <= upperDateTimeInclusive);
 }

 

Step 2: Add UI to execute the query

To call the search query instead of the GetTasks query that the DomainDataSource in the UI currently calls at page load, you need to add some UI. Open up MainPage.xaml and click on the DataGrid that is filling the UI. Grab the top edge and drag it down a bit to make room for a few controls. Drag and drop two TextBoxes and one Button so that it looks something like the screen shot below.

UIModification

Name the first TextBox lowerDate and the second upperDate and the button searchButton. Set the Content of the button to Search By Date. Double click on the button to add a handler.

Step 3: Execute a query on the client through the DomainContext

If you remember from the introduction in Part 1, the DomainContext is the code generated client side counterpart to the server side domain service. In this case, since the domain service is called TasksDomainService, the client counterpart is called TasksDomainContext. It exposes the ability to call the server side asynchronously and to also submit changes made to entities on the client side. The DomainContext is really the brains of the WCF RIA Services on the client side and has a lot of stuff going on internally. Whenever you retrieve entities from the server by executing a query through the domain context, the domain context also holds a reference to those objects along with some change tracking information. So if you modify those objects, it knows which have changed and can send just those entities back to the server side when you decide to submit those changes. But I’ll get into that some more in the next article. For now, lets stay focused on the retrieval side of things.

In your search button click handler, you could add the following code:

 private void searchButton_Click(object sender, RoutedEventArgs e)
 {
     DateTime lowerDateVal;
     DateTime upperDateVal;
     GetDates(out lowerDateVal, out upperDateVal);
  
     TasksDomainContext context = new TasksDomainContext();
     taskDataGrid.ItemsSource = context.Tasks;
     EntityQuery<Task> query = context.GetTasksByStartDateQuery(lowerDateVal, upperDateVal);
     LoadOperation<Task> loadOp = context.Load(query);
 }

The important code here are the last four lines. To call the server side, you need an instance of a domain context. In a real application, you are going to want to create an instance of the domain context that you keep around for a while, because that is where the change tracking information for submitting changes resides. So you will typically move it to a member variable in a view model or possibly an application scoped service. But I’ll get into more detail on that in Part 4 of the series.

The domain context exposes collections of entities that include the sets of collections returned by query methods on your domain service. So far the domain service just exposes a collection of Tasks. Notice that the code is replacing the ItemsSource of the DataGrid with the Tasks collection on this domain context before making any calls against it. This is because when you query through the domain context, the queries execute asynchronously and will replace the contents of the exposed collection when the query returns from the server. That collection implements INotifyCollectionChanged and will raise events that causes the DataGrid (or any data bound control) to refresh itself when those events fire.

The code then gets an EntityQuery<Task> from the context with the arguments that are passed to the corresponding domain service method. That just sets up what you want done, it doesn’t actually make a call. Finally, it gets a LoadOperation<Task> from the context by calling Load. This is the point where a call is actually made to the server, on a background thread, and automatically marshalling the changes onto the UI thread to modify the collection when the results come back.

This is the same thing that is happening under the covers on the DomainDataSource that was used in the XAML in Part 1.

The GetDates method above just extracts the dates from the TextBoxes, checking for empty strings.

Step 4: Add query methods that return a single entity

To return a single entity instead of a collection, you just define a method that does so on your domain service. A corresponding query method will show up on your domain context after compiling.

 public Task GetTask(int taskId)
 {
     return this.ObjectContext.Tasks.FirstOrDefault(t => t.TaskId == taskId);
 }

Convention Over Configuration

This is an emerging trend in .NET development– reduce the amount of explicit configuration you need in your code and rely on some naming conventions. It may not be apparent from the domain service code so far, but it has actually been relying on convention. It is not obvious on the query side of things, because any method name will work. But for update, insert, and delete methods, there are a set of named prefixes WCF RIA Services is looking for, such as UpdateTask, InsertTask, and DeleteTask (or a number of variants for each operation).

You can also use “configuration” by decorating the methods with attributes to indicate what kind of operation it is. For the Query side, the attribute is named, not surprisingly, [Query]. Using the attribute can make your code more explicit by making it easy to recognize at a glance what kind of method it is. But the IQueryable<T>, IEnumberable<T> or Entity return type makes it pretty obvious it is a query method anyway. The one advantage of using the Query attribute is that it supports a couple of additional things, such as specifying a maximum number of results (entity count) to return even if the underlying query returns more from the database.

Custom Domain Services

What if you don’t want to use Entity Framework? Another choice is LINQ to SQL. Personally, I would recommend that if you are starting a new project, you focus on Entity Framework. It is really the most capable and likely to be long-lived data access approach for .NET now and in the future. LINQ to SQL is also supported through the separate WCF RIA Services Toolkit if you really want to use that instead.

But a lot of people are using other data access strategies (i.e. nHibernate) and other data sources (Oracle, MySQL, etc.). You can easily use those with WCF RIA Services as well, as long as you can define the data objects you want to pass as simple entities and populate those using whatever code you need to. These are referred to as POCO (Plain Old CLR Objects) domain services.

To do this, you just derive your domain service class from DomainService directly, instead of using the LinqToEntitiesDomainService base class. In the wizard when you Add > New Item > Domain Data Service, just select “empty domain service class” in the Available DataContext/ObjectContext classes drop down. Then define your own entities, return IEnumerable<T> collections of those entities for queries if your underlying data source does not support IQueryable<T>, and do whatever you need to do based on your data source in the methods.

POCODomainService

Then you would define your service in terms of your underlying data source and the entities that you are working with. The entity types you work with need to have properties that are other entities or a set of supported types that include all the built in types of the .NET framework.

The key (pun intended) thing that distinguishes your entities is that they need to have a key properties that uniquely identifies them. This is typically an int or Guid. You indicate that property with the [Key] attribute.

The code below shows a simple POCO domain service and its entity type.

 public class Foo
 {
     [Key]
     public int FooId { get; set; }
     public string Name { get; set; }
 }
  
 [EnableClientAccess()]
 public class MyPOCODomainService : DomainService
 {
     public IEnumerable<Foo> GetFoos()
     {
         return new List<Foo> { new Foo { FooId = 42, Name = "Fred" } };
     }
 }

 

In addition to the [Key] attribute, if you have properties on your entity that are entity types themselves (related entities or associations), then you will need to have a property along side that entity that is an ID for that entity that gets set to its key field. Additionally, on the entity property itself, you will need an [Association] attribute to indicate the ID property that sets up the relation and indicate that it is a foreign key. On the entity property, you will also need an [Include] attribute to have that related entity also retrieved when the parent entity is retrieved to the client by RIA Services. See the MSDN Library documentation for these attributes for more information.

Summary

In this article, you got a taste of how queries work with WCF RIA Services. You saw one way to query programmatically and bind to the results. You saw how to define additional query methods and learned about the conventions and configuration options for indicating your query methods in your domain service. You also learned about exposing POCO domain services. In the next article, I’ll show how to make changes to entities on the client side and get those changes made on the server.

The finished code for this article can be downloaded here.

About the Author

Brian Noyes is Chief Architect of IDesign, a Microsoft Regional Director, and Connected System MVP. He is a frequent top rated speaker at conferences worldwide including Microsoft TechEd, DevConnections, DevTeach, and others. He is the author of Developing Applications with Windows Workflow Foundation, Smart Client Deployment with ClickOnce, and Data Binding in Windows Forms 2.0. Brian got started programming as a hobby while flying F-14 Tomcats in the U.S. Navy, later turning his passion for code into his current career. You can contact Brian through his blog at http://briannoyes.net.


Subscribe

Comments

  • -_-

    RE: WCF RIA Services Part 2: Querying Data


    posted by Rachida Dukes on Jun 24, 2010 14:58
    Thanks so much for doing these series, they're very helpful when we want to learn silverlight.
  • -_-

    RE: WCF RIA Services Part 2: Querying Data


    posted by Chuck Snyder on Jun 24, 2010 22:06

    Thanks for the work on these tutorials, really helps me get started with EF and Silverlight.

    But I do have one question (you'll probably get to it later), I need to retrieve some data from EF and work with it before displaying it on the screen.  Could you show me a simple example of walking down thru the data and processing each row??

     

    Thanks Chuck

  • -_-

    RE: WCF RIA Services Part 2: Querying Data


    posted by Brian Noyes on Jun 29, 2010 23:12
    Chuck: see the following post: http://briannoyes.net/2010/06/29/QueryingWCFRIAServicesAndHandlingAsyncResults.aspx
  • -_-

    RE: WCF RIA Services Part 2: Querying Data


    posted by Dario on Jul 06, 2010 15:30
    Your tutorial is great! Dario from Rome, Italy
  • -_-

    RE: WCF RIA Services Part 2: Querying Data


    posted by Compuanalisis on Jul 09, 2010 04:13
    Wonderfull article, But you can drag and drop directly from the datasource into mainpage without writing any piece of code, and works perfectly.
  • -_-

    RE: WCF RIA Services Part 2: Querying Data


    posted by Rüdiger on Jul 14, 2010 10:50

    Nice article.

    Would be wonderful to make a real example for e.g. Oracle->Pocos->DataService->Context->MVVM->View with service containing functions and queries.

  • -_-

    RE: WCF RIA Services Part 2: Querying Data


    posted by Gary G on Jul 23, 2010 20:46

    Great series, Thank you for your time and effort.

    My client side generated classes (...web.g.cs) have namespaces generated like: proj.Web.Models, Proj.Web.Views while your code has generated TaskManager and TaskManager.Web --  different code is being generated. What version of Silverlight  SDK are you using (mine is April 2010)? There appears to be some other differences as well.

  • -_-

    RE: WCF RIA Services Part 2: Querying Data


    posted by Brian Noyes on Jul 23, 2010 22:11
    Gary, I am using the released version of the Silverlight 4 Tools for Visual Studio, which is how RIA Services shipped in May. However, I just noticed that download was updated on 7/7 so am updating my tools to that latest release.
  • -_-

    RE: WCF RIA Services Part 2: Querying Data


    posted by Gary G on Jul 24, 2010 02:50

    Great series, Thank you for your time and effort.

    My client side generated classes (...web.g.cs) have namespaces generated like: proj.Web.Models, Proj.Web.Views while your code has generated TaskManager and TaskManager.Web --  different code is being generated. What version of Silverlight  SDK are you using (mine is April 2010)? There appears to be some other differences as well.

  • -_-

    RE: WCF RIA Services Part 2: Querying Data


    posted by technette on Jul 27, 2010 19:28
    Thank you!  Once I finally got my navigation, design and connectivity going.  This is like candy because of the diversity of ways to query and display the data.
  • -_-

    RE: WCF RIA Services Part 2: Querying Data


    posted by Robin on Aug 02, 2010 14:36
    Very keen to view your next Post on MVVM and WCF RIA Services. When it is going to be posted?
  • -_-

    RE: WCF RIA Services Part 2: Querying Data


    posted by Brian Noyes on Aug 03, 2010 07:58
    Already submitted, should hit the wire any day now
  • -_-

    RE: WCF RIA Services Part 2: Querying Data


    posted by Glen on Oct 13, 2010 13:42
    I am using .Net 3.5 as only have Visual Studio 2008 SP1 available. I don't seem to be able to reference System.ServiceModel.DomainServices.Client as it doesn't exist. Is there some alternative?
  • -_-

    RE: WCF RIA Services Part 2: Querying Data


    posted by Brian Noyes on Oct 13, 2010 13:44
    Glen, RIA Services is only supported in .NET 4 / SL 4 in VS 2010.
  • -_-

    RE: WCF RIA Services Part 2: Querying Data


    posted by Glen on Oct 13, 2010 15:08

    I have now completed this article with .Net 3.5 in VA 2008 SP1

     System.ServiceModel.DomainServices.Client from Silverlight 4 is contained in System.Windows.Ria in Silverlight 3

  • -_-

    RE: WCF RIA Services Part 2: Querying Data


    posted by Glen on Oct 13, 2010 15:09
    I meant VS 2008 SP1
  • -_-

    RE: WCF RIA Services Part 2: Querying Data


    posted by Brian Noyes on Oct 13, 2010 15:13
    Glen, be aware the code that works with VS 2008 was pre-release beta code that was not updated with all the changes that went into the 4.0 release and will not be updated or supported. I would not build any real apps against that and using it will teach you certain coding patterns that do not apply to the final release.
  • -_-

    RE: WCF RIA Services Part 2: Querying Data


    posted by Glen on Oct 13, 2010 15:35
    Ok thanks Brian.
  • silver123

    RE: WCF RIA Services Part 2: Querying Data


    posted by silver123 on Nov 15, 2010 14:32

    thanks!!

    But my query is how to query data using multiple criteria like empid,cadreid in combo boxes and selecting the criteria from combo box and clicking on search it should display record in grid.

  • -_-

    RE: WCF RIA Services Part 2: Querying Data


    posted by Brian Noyes on Nov 15, 2010 14:58
    Silver123: As long as those multiple criteria are based on properties of the entity or its related entities that are brought down during the query as [Include] properties on the root entity, it should just be a matter of expressing them all as part of the LINQ expression on the EntityQuery<T> object when you call Load.
  • -_-

    RE: WCF RIA Services Part 2: Querying Data


    posted by Silver123 on Nov 16, 2010 07:37

    Thanks for your reply!!

    Could you please explain it by giving any example (Require the code).

    My scenareo is as following:

    i have three comboboxes

    1)empid  -> empids should be loaded from master table say Employee_Master

    2)cadreid ->cadreid shud be loaded from master table say Cadre_Master

    there will be one Search button and datagrid

    On  selecting empid and cadreid from combo box and Clicking on search button it should get data from Transaction table say Emp_Trans and display it in the datagrid.based on the selected criteria.

    Your help will be appreciated..

     

  • -_-

    RE: WCF RIA Services Part 2: Querying Data


    posted by Brian Noyes on Nov 16, 2010 11:50

    Assuming that your Emp_Trans table has foreign key columns empid and cadreid in it, you would do the following:

    - define a GetEmployeeTransactions method on your domain service that returns ObjectContext.Emp_Trans

    - then the code in your domain context would look like

    EntityQuery<EmpTrans> query = _EmployeesDomainContext.GetEmployeeTransactionsQuery();

    _EmployeesDomainContext.Load(query.Where(emp=>emp.empid = selectedEmpId && emp.cadreid == selectedCadreId);

    When load completed, you should have your filtered data. In this case you don't even need the Include on the object context or the metadata class if you are just returning a single row since the filtering actually happens at the database.

  • -_-

    RE: WCF RIA Services Part 2: Querying Data


    posted by Silver123 on Nov 16, 2010 14:53

    In the above example u have used textboxes for criteria.

    If i want to use comboboxes and fill those combo boxes with values from master table..what would be the code for that.

    Also in that case what change will be in the above code that u have given.

    How to retrive values from comboboxes and use it in query.

    Thanks!!

  • -_-

    RE: WCF RIA Services Part 2: Querying Data


    posted by Brian Noyes on Nov 16, 2010 15:08
    Those would just be separate queries you would need to expose from your domain service to pull down the list of Employees and the list of Cadres. Then you would have two more Load calls with no filter criteria on them through the domain context.
  • -_-

    RE: WCF RIA Services Part 2: Querying Data


    posted by Steve on Nov 16, 2010 23:03
    How to cache queries - ie. lookup tables ?
  • -_-

    RE: WCF RIA Services Part 2: Querying Data


    posted by Brian Noyes on Nov 17, 2010 00:07

    Steve,

    Once you have done a Load, the returned entities are cached in the exposed collection on the DomainContext, i.e. myContext.MyLookupValues. You can just re-bind to that collection anywhere you need it. For those usage scenarios (i.e. potentially many views that depend on those values), I would move my DomainContext out to a service (in process service based on the service locator pattern), do the Load once there, and just expose the collection owned by the DataContext via a collection property or method on the service that I can grab and bind to from many UIs.

  • -_-

    RE: WCF RIA Services Part 2: Querying Data


    posted by Silver123 on Nov 17, 2010 12:42

    Hi,

    following is the code in my domain service for geting list of cadreids from cadre_master table

    public int GetCadreID()
    {
     
    return this.ObjectContext.Master_Cadre.Select(t => t.Cadre_ID);
    }

    but i want to return all cadreids so what would be the return type of the function.

    i have tried:

    IQueryable<Master_Cadre>, IEnumerable<>

    but no success.

    Please help..

     

  • -_-

    RE: WCF RIA Services Part 2: Querying Data


    posted by Brian Noyes on Nov 17, 2010 13:56
    Silver123: Just remove your Select and return an IQueryable. Obviously if you filter to a single ID, you are only going to return one object. Don't filter.
  • -_-

    RE: WCF RIA Services Part 2: Querying Data


    posted by MarkSe on Dec 31, 2010 15:04

    Brian,

    i am trying to get Eager loading working - environment is silverlight 4 / .net 4.

    basically, table structure is

    PromoHeader has 0 to many PromoGroups

    PromoGroup has 0 to many PromoItems

    PromoItem has 1 Item

    Item has several lookups

    Code in ViewModel (based on briannoyes.net/2010/06/29/QueryingWCFRIAServicesAndHandlingAsyncResults.aspx)

        public PromoBuilderReviewPromoItemsVM()
        {
          PageItems = new ObservableCollection<PromoHeaderDetail>();
          Hydra2DomainContext hydraContext = new Hydra2DomainContext();
          EntityQuery<PromoHeaderDetail> phdQuery = hydraContext.GetPromoHeaderDetailsAllDetailsQuery();
          Action<LoadOperation<PromoHeaderDetail>> completeProcessing = delegate(LoadOperation<PromoHeaderDetail> loadOp)
          {
            if (!loadOp.HasError)
            {
              ProcessTasks(loadOp.Entities);
            }
            else
            {
              LogAndNotify(loadOp.Error);
            }
          };
          LoadOperation<PromoHeaderDetail> loadOperation = hydraContext.Load(phdQuery.Where(t => t.StartDate > DateTime.Parse("2011-01-01 00:00:00")), completeProcessing, null);
        }
        private void ProcessTasks(IEnumerable<PromoHeaderDetail> entities) 
        {
          var ii = 0;
          foreach (var promoHeader in entities)
          {
            ii++;
            PageItems.Add((PromoHeaderDetail)promoHeader);
            foreach (var promoGroup in promoHeader.PromoGroupDetails)
            {
              foreach (var promoItem in promoGroup.PromoItemDetails)
              {
                PageItems2.Add((Item)promoItem.Item);
              }
            }
          }
        }
        private void LogAndNotify(Exception error)
        {
          // Log the error and notify user if appropriate
        }

    and in the Domain Service

        public IQueryable<PromoHeaderDetail> GetPromoHeaderDetailsAllDetails()
        {
          this.ObjectContext.ContextOptions.LazyLoadingEnabled = false;
          return this.ObjectContext.PromoHeaderDetails.Include("PromoGroupDetails.PromoItemDetails.Item.Lookup");
        }
    
    when i run this code - and review using SQL profiler, the query is reading all of the tables and including the "sub-tables".
    however, in the code, while query is returning correct number of PromoHeader records - none of them have any PromoGroup records 
    or PromoItems that could be seen in the T-SQL query in profiler.
    so - the correct data in being read - but not returned....
    thx
    (and a happy New Year)
    ps. have also posted this on MSDN forum...
     

     

  • -_-

    RE: WCF RIA Services Part 2: Querying Data


    posted by Brian Noyes on Dec 31, 2010 15:47
    MarkSe,Did you add the [Include] attributes in the metadata "buddy" classes for the entity relations?
  • -_-

    RE: WCF RIA Services Part 2: Querying Data


    posted by markse on Jan 01, 2011 13:19

    Brian

    thx for the quick response..... oops - no i hadn't.

    now works for the first couple of levels

    i.e. i can now eager load the PromoGroupDetails and the PromoItemDetails when loading the Header Details.

    return

     

     

    this.ObjectContext.PromoHeaderDetails.Include("PromoGroupDetails.PromoItemDetails");

    but i get an error when i try and load the Item details (there is one of these for each PromoItemDetails record i.e. a 1 <-> 1 relationship). as far as i can see, problem is due to there being only one Item per ItemDetails record and therefore the [Include] attibute wont work as it works on an ObjectSet rather than an individual entity

     

    is there a way around this to "bulk load" the item details i - or do i need to loop around the resultset i have got an then read the item record directly (by id).........

     

     

     

     

  • -_-

    RE: WCF RIA Services Part 2: Querying Data


    posted by markse on Jan 01, 2011 13:21

    brian

    or might it be betterto use a view / stored procedure ??

    m

  • -_-

    RE: WCF RIA Services Part 2: Querying Data


    posted by Brian Noyes on Jan 01, 2011 20:26
    Mark, [Include] attribute works for single object (i.e. Parent) references as well. But your entity framework query is not loading through the Item association. However, in general I have found it problematic to load up entire object graphs with eager loading in EF. Generally for those scenarios I find it easier to give up on the deferred execution, define my method as an IEnumerable<T> instead of IQueryable<T>, and then I can progressively load up all the related objects myself.
  • -_-

    RE: WCF RIA Services Part 2: Querying Data


    posted by Alex on Jan 27, 2011 19:02
    sorry, maybe i've missed something, but then i set dates and push the "Search By Date" nothing happen, i downloaded finished code of this article and run it on VWD 2010 Express and SQL Server 2005 Express with TaskManager DataBase on it. Use SL4, WCF RIA Services Toolkit December 2010. What can i do wrong?
  • -_-

    RE: WCF RIA Services Part 2: Querying Data


    posted by Brian Noyes on Jan 30, 2011 22:32
    Alex: Does the grid load with four rows when you first run the app? If not, then it is probably a connection string problem. Part 8 in this series talks about debugging RIA Services apps. If you are running SQL Express, you will have to modify the connection string in the web.config file of the hosting site to point to your named instance of SQL Express (.\SQLExpress by default) instead of the default server it points to in the download code (server=. should be switched to server=.\SQLEXPRESS).
  • AfonsoGomes

    Re: WCF RIA Services Part 2: Querying Data


    posted by AfonsoGomes on Jun 08, 2011 18:04

    I'm trying to get the retrieved single entity, but i don't know how to do it in the client. How can i call the method GetTask(int TaskID) and receive the Task in the client?

     

    Thanks,

    Afonso Gomes

  • brian.noyes

    Re: WCF RIA Services Part 2: Querying Data


    posted by brian.noyes on Jun 09, 2011 03:07

    Afonso,

    You get one query method on the domain context for each query method you expose from the domain service. The one mappiing to GetTask is:

    EntityQuery<Task> GetTaskQuery(int taskId) 
    So similar to getting all tasks, you would pass that query object to the Load method:
    _TasksDomainContext.Load(GetTaskQuery(taskId));
  • AfonsoGomes

    Re: WCF RIA Services Part 2: Querying Data


    posted by AfonsoGomes on Jun 09, 2011 17:25

    But I don't want to bind directly to some control in the design.

    My entity that I want is called Planta. And what I need is to manipulate a Planta entity, not an EntitySet<Planta>.

    For that I'm making:

    _Context.Load(_Context.GetPlantaByIdQuery(Int32.Parse(plantaEscolhida)));
    EntitySet<Planta> p = _Context.Plantas;
    
    foreach (Planta pl in p)
                {
                    MessageBox.Show(pl.id_planta + " " + pl.nome + "\n");
                    Planta plantaSeleccionada = pl;
                }
     
    (I've tried with the definition of p before calling the load and the result was the same).
    I'm showing in a MessageBox to see how many Plantas there is in the entity. 
    For testing purposes, I have two Plantas in the database.
    In the constructor of the class I load all the Plantas, because I need them: 
    public ViewerViewModel()
            {
                this.timer.Duration = TimeSpan.FromSeconds(1);
                this.timer.Completed += new EventHandler(timer_Tick);
                _Context = new TesteDomainContext();
                _Context.Load(_Context.GetPlantasQuery());
            }
     
    So I don't know if the previous load is anything to do with the other load.
     
    Btw, I'm using SL5 with Ria Services SP2.
  • brian.noyes

    Re: WCF RIA Services Part 2: Querying Data


    posted by brian.noyes on Jun 10, 2011 03:38
    When your context loads a collection of a given entity type, it caches them and just refreshes them if subsequent loads happen. So once you have retrieved both of them with the other query, the second query getting just one just makes sure that entity is in the cache as is current. If you want to just get the one you can either new up a new domain context and execute the query with it, or Clear() the entity collection on the one you are using before the call to Load with GetPlantaByIdQuery so that only that one will be in the collection after the async load completes.
  • jj2011

    Re: WCF RIA Services Part 2: Querying Data


    posted by jj2011 on Aug 14, 2011 08:56

    I've tried following your example, but I cannot get my query to work.  When a user selects an item in the grid, I want to take they key value selected and use it to query for the detail data.  I cannot bind this data because the resulting item coming from the server is rtf text to a richtext control.  Here is a sample of my code:

     

     

    vResourceName selItem = (vResourceName)vResourceNameDataGrid.SelectedItem;

     

     

     

     

    SmartGridContext context = new SmartGridContext();

     

     

     

     

    EntityQuery<ResourceItem> query = context.GetResourceItemsByIDQuery(selItem.ResourceID);

     

     

     

     

    LoadOperation<ResourceItem> loadOp = context.Load(query);

     

     

     

     

    if (loadOp.Entities.Count() > 0)

     

    {

     

     

     

    ResourceItem NewResource = loadOp.Entities.LastOrDefault();

    }

    The Entities count is always 0, indicating no data was returned.  I' stuck.

     

     

  • jj2011

    Re: WCF RIA Services Part 2: Querying Data


    posted by jj2011 on Aug 14, 2011 08:56

    I've tried following your example, but I cannot get my query to work.  When a user selects an item in the grid, I want to take they key value selected and use it to query for the detail data.  I cannot bind this data because the resulting item coming from the server is rtf text to a richtext control.  Here is a sample of my code:

     

     

    vResourceName selItem = (vResourceName)vResourceNameDataGrid.SelectedItem;

     

     

     

     

    SmartGridContext context = new SmartGridContext();

     

     

     

     

    EntityQuery<ResourceItem> query = context.GetResourceItemsByIDQuery(selItem.ResourceID);

     

     

     

     

    LoadOperation<ResourceItem> loadOp = context.Load(query);

     

     

     

     

    if (loadOp.Entities.Count() > 0)

     

    {

     

     

     

    ResourceItem NewResource = loadOp.Entities.LastOrDefault();

    }

    The Entities count is always 0, indicating no data was returned.  I' stuck.

     

     

  • brian.noyes

    Re: WCF RIA Services Part 2: Querying Data


    posted by brian.noyes on Aug 14, 2011 16:59
    Load is an asynchronous operation, you have to handle a callback or the Completed event to see the resulting entities.
  • jj2011

    Re: WCF RIA Services Part 2: Querying Data


    posted by jj2011 on Aug 15, 2011 06:32
    Thank you for your response.  I am one week into coding my first siverlight app.  Could you provide a sample procedure to show how to handle the callback?
  • brian.noyes

    Re: WCF RIA Services Part 2: Querying Data


    posted by brian.noyes on Aug 15, 2011 14:00
    Please read further into the series, this is covered in parts 3 and 4.
  • furqan.safdar

    Re: WCF RIA Services Part 2: Querying Data


    posted by furqan.safdar on Aug 20, 2011 12:42

    while executing the line:

    LoadOperation<Task> loadOp = context.Load(query);

    following exception is encountered:

    Could not load file or assembly 'System.ServiceModel.Web, Version=2.0.5.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e' or one of its dependencies. Invalid assembly file format. (Exception from HRESULT: 0x8013141D)

    Please let me know what is this issue and how to resolve it?

    Thanks

  • brian.noyes

    Re: WCF RIA Services Part 2: Querying Data


    posted by brian.noyes on Aug 21, 2011 23:24
    Most likely you have your server project set to the .NET 4 Client Profile in the project application settings, need to change it to be full .NET 4.
  • eilering

    Re: WCF RIA Services Part 2: Querying Data


    posted by eilering on Sep 11, 2011 13:46

    I downloaded the file and opened it in VS2010

    I got an error eg on main.aspx

    <

     

     

    my:TasksDomainContext />

    was not found. make sure you are not missing an assembly reference.

    help

     

     

  • brian.noyes

    Re: WCF RIA Services Part 2: Querying Data


    posted by brian.noyes on Sep 11, 2011 14:10

    Not sure how to help with that since there is no main.aspx in the solution. You need to download, unzip, open the solution, build, and make sure the TaskManagerTestPage.aspx is set as the start page for the web app. Then do a debug run with the web app as the startup project. If you have problems at that point, give me some more specifics and I can probably help. I would recommend you read a little further into the series, because I talk about debugging and handling errors in several of the upcoming articles in the series.

    Brian

  • haiyun592

    Re: WCF RIA Services Part 2: Querying Data


    posted by haiyun592 on Jan 09, 2012 21:08

    Please Help,

    Instead of displaying the returned data in a data grid, how can I get a single value from the domain context and assign the value to a variable?

    Thanks!

  • brian.noyes

    Re: WCF RIA Services Part 2: Querying Data


    posted by brian.noyes on Jan 10, 2012 15:51
    haiyun592, please see my answer to your similar question in Part 1 of the series.
  • stratdaz

    Re: WCF RIA Services Part 2: Querying Data


    posted by stratdaz on Jan 11, 2012 05:15

    I need to process associated (child) entites from a query. Problem is the child entities are not always populated by the time the callback is fired.

    Here is an example where "Clients" and "ClientOrders" are ViewModel properties ...

    private void GetClient()
            {
                _domainContext.Load(_domainContext.GetClientsQuery(), lo =>
                {
                    Client client = lo.Entities.FirstOrDefault(c => c.ClientId == 1);
                    int orderCount = client.ClientOrders.Count();
                }, null);
            }

    The first time I run this query for a client (say client 1) "orderCount" is nearly always 0. When I select another client and then reselect client 1 "orderCount" has the correct number of client orders.

    It seems the callback is triggered when the client entity query has completed and does not wait until all associated entities are populated.

    Is there an event related to the population of the child entity collection that I can hook into?

    Thanks.

  • stratdaz

    Re: WCF RIA Services Part 2: Querying Data


    posted by stratdaz on Jan 11, 2012 05:17

    Oops, please ignore the line ...

    "Here is an example where "Clients" and "ClientOrders" are ViewModel properties ..."

     

  • stratdaz

    Re: WCF RIA Services Part 2: Querying Data


    posted by stratdaz on Jan 11, 2012 07:16

    Oops, please ignore the line ...

    "Here is an example where "Clients" and "ClientOrders" are ViewModel properties ..."

     

  • stratdaz

    Re: WCF RIA Services Part 2: Querying Data


    posted by stratdaz on Jan 11, 2012 07:58

    Oops, please ignore the line ...

    "Here is an example where "Clients" and "ClientOrders" are ViewModel properties ..."

     

  • brian.noyes

    Re: WCF RIA Services Part 2: Querying Data


    posted by brian.noyes on Jan 15, 2012 17:36

    stratdaz,

    I'm not sure what would cause the behavior you describe. If the child entity collection is marked on the server side entities with an [Include] attribute, and the Entity Framework query loads the entities with an .Include() call, then you can fire up Fiddler and see that the child entities are returned with the parent entites in a single request to the server. So you should be able to reliably use the child collection property (not member variable) on the Parent entities returned from the Load call in the completed handler and the child entities should be available immediately with no delay.

  • manjerekarrao

    Re: WCF RIA Services Part 2: Querying Data


    posted by manjerekarrao on Jan 25, 2012 14:30

    Hi Brian,

    i created my TaskModel.edmx in a separate class library and not in TaskManager.Web server

    project.

    when i try adding TasksDomainService in the TaskManager.Web project, i see that the

    'Generate associated classes for metadata' option is disabled. I still went ahead and added

    the TasksDomainService. Rebuilt the complete solution and when i finally executed the

    application i get this error.....

    System.ServiceModel.DomainServices.Client.DomainOperationException: Load operation failed

    for query 'GetTasks'. The remote server returned an error: NotFound. --->

    System.ServiceModel.CommunicationException: The remote server returned an error: NotFound.

    ---> System.Net.WebException: The remote server returned an error: NotFound. --->

    System.Net.WebException: The remote server returned an error: NotFound.
       at System.Net.Browser.BrowserHttpWebRequest.InternalEndGetResponse(IAsyncResult

    asyncResult)
       at System.Net.Browser.BrowserHttpWebRequest.<>c__DisplayClass5.<EndGetResponse>b__4

    (Object sendState)
       at System.Net.Browser.AsyncHelper.<>c__DisplayClass4.<BeginOnUI>b__1(Object sendState)
       --- End of inner exception stack trace ---
       at System.Net.Browser.AsyncHelper.BeginOnUI(SendOrPostCallback beginMethod, Object

    state)
       at System.Net.Browser.BrowserHttpWebRequest.EndGetResponse(IAsyncResult asyncResult)
       at

    System.ServiceModel.Channels.HttpChannelFactory.HttpRequestChannel.HttpChannelAsyncRequest.

    CompleteGetResponse(IAsyncResult result)
       --- End of inner exception stack trace ---
       at System.ServiceModel.DomainServices.Client.WebDomainClient`1.EndQueryCore(IAsyncResult

    asyncResult)
       at System.ServiceModel.DomainServices.Client.DomainClient.EndQuery(IAsyncResult

    asyncResult)
       at System.ServiceModel.DomainServices.Client.DomainContext.CompleteLoad(IAsyncResult

    asyncResult)
       --- End of inner exception stack trace ---

     

    Request you to pls help me in this issue.

     

    Thank you

    Manjerekar

     

  • brian.noyes

    Re: WCF RIA Services Part 2: Querying Data


    posted by brian.noyes on Jan 26, 2012 02:06

    Manjerekar, Did you add the connection string to the web.config?

  • stratdaz

    Re: WCF RIA Services Part 2: Querying Data


    posted by stratdaz on Jan 27, 2012 00:49

    Brian,

    Looks like I needed to have the .Include("ChildEntities") in the domain service class to fix this one. Threw me off when I didn't have that but it still worked 95% of the time?

    Anyway, hoping it's reliable now.

    Thanks.

  • manjerekarrao

    Re: WCF RIA Services Part 2: Querying Data


    posted by manjerekarrao on Feb 02, 2012 15:21

    hi Brain,

    is there a way where we can catch up on skype.

  • haiyun592

    Re: WCF RIA Services Part 2: Querying Data


    posted by haiyun592 on Apr 21, 2012 20:40
    Brian, I am trying to use a ComboBox in a Data Form to display company department names in my RIA application,  could you please tell me how to use it. Thanks!
  • brian.noyes

    Re: WCF RIA Services Part 2: Querying Data


    posted by brian.noyes on Apr 21, 2012 20:52
    Retrieve the collection through your domain context, expose a property from your view model like I have done in the samples that surfaces the collection from the domain context for binding from the view. Then bind your ComboBox ItemsSource to that property.
  • haiyun592

    Re: WCF RIA Services Part 2: Querying Data


    posted by haiyun592 on Aug 16, 2012 03:29

    There are two tables in my domaincontext 1. Personnel 2.Department, Personnel has foreign key to Department.

    In the ViewMode, I have the following code

            public IEnumerable<Personnel> Personnels { get; set; }
            public IEnumerable<Department> Departments { get; set; }

            public HomeViewModel()
            {
                Personnels = _context.Personnels;
                Departments = _context.Departments;
                if (!DesignerProperties.IsInDesignTool)
                {
                    _context.Load(_context.GetPersonnelsQuery());
                    _context.Load(_context.GetDepartmentsQuery());               
                }
            }

    In the View, my XAML is

    <sdk:DataGrid AutoGenerateColumns="True" Name="dataGrid1" ItemsSource="{Binding Path=Personnels, Mode=TwoWay}" />

    <df:DataForm x:Name="myDF" CurrentItem="{Binding SelectedItem, ElementName=dataGrid1}">
                        <df:DataForm.EditTemplate>
                            <DataTemplate>
                                <StackPanel>
    ...
                                       <df:DataField Label="Department">
                                            <ComboBox ItemsSource="{Binding Departments, Mode=TwoWay}" />
                                    </df:DataField>
                               </StackPanel>
                            </DataTemplate>
                        </df:DataForm.EditTemplate>
                    </df:DataForm>

    But there is no data populated in the combobox. Could you please help. Thanks!

     

  • brian.noyes

    Re: WCF RIA Services Part 2: Querying Data


    posted by brian.noyes on Aug 16, 2012 06:14

    First off if you want to display related item, you would not query the personnel and departments collection separately, you would need to make sure that each personnel record returns its related departments. You would do this with an Include() statement on your EF query and an [Include] attribute on the Departments collection property on the Personnel class.

    Second, the data binding for the details form would need to get the SelectedItem.Departments collection off the currently selected Personnel item in the data grid.

    Take a closer look at the master details scenarios in my articles and you will see examples just like this.


  • payohtee

    Re: WCF RIA Services Part 2: Querying Data


    posted by payohtee on Nov 23, 2012 02:39

    Hi, Brian.

    I am embarrassed to reveal my true level of ignorance, but what the heck. I read with enthusiasm your first and second article on WCF-RIA services. They were extremely helpful, so I thank you sincerely. I also downloaded both projects, but I can get neither to run on my system. I'm using VS2011 Beta. When I try to run either project, I receive the following error message:

    The Silverlight project you are about to debug uses WCF-RIA services. WCF RIA services will fail unless the Silverlight project is hosted in and launched from the same web project that contains the WCF RIA services. Do you want to debug anyway.

    If I click on Yes, I get a run-time error in the browser, and I can go no farther.

    This question is probably out of context for your articles, so if you want to simply point me somewhere, that would be thoroughly acceptable to me. Also, if you want to *ignore* such a baby question, that too is thoroughly acceptable! :-)

    Thanks for your attention to this matter.

    Pay

  • brian.noyes

    Re: WCF RIA Services Part 2: Querying Data


    posted by brian.noyes on Nov 23, 2012 15:54

    Hi Pay,

    Not sure why you would be bothering with VS 11 Beta when it is released, but the simple fact is that when an author puts out an article / book / publication, it is impossible to expect that their sample code will work correctly with future releases of the tools that they don't have access to at the time, especially a beta release of a future product. 

    That being said, the samples open and run fine for me in Visual Studio 2012. You do get some conversion warnings, but those are just because it has to update some references when it brings it into the VS 2012 environment.

Add Comment

Login to comment:
  *      *       

From this series