Search code examples
silverlightentity-frameworklinq-to-entitiesprismwcf-ria-services

WCF RIA EntityQuery returns null for Foreign Keys


I'm following a tutorial on Silverlight and Prism, where WCF RIA Services are uses to access the Northwind database through an ADO.NET Entity Data Model.

In the Northwind database, there is a table Order_Details which is connected to two other tables (Orders and Products) via foreign keys:

Picture of Data Model

The code to query the database looks like this:

EntityQuery<Order_Detail> detailQuery = _MyDomainContext.GetOrder_DetailsQuery();

_MyDomainContext.Load(detailQuery.Where(
            det => det.Order.Customer.CustomerID == cust.CustomerID).OrderByDescending(
            det => det.Order.OrderDate).Take(10), OnDetailsLoaded, null);

and then in OnDetailsLoaded:

var details = loadOp.Entities;
if (details != null)
        {
            var detailsList = details.ToList();
            detailsList.ForEach(det => Orders.Add(
                new OrderItem
                {
                    ProductName = det.Product.ProductName,
                    Quantity = det.Quantity,
                    OrderDate = det.Order.OrderDate.Value
                }));

This gives me a Null Exception at new OrderItem, because both Product and Order are null. I have set my EntityDataModel to "Include Foreign Key Columns in the Model". The code is exactly as in the tutorial, I only had to recreate the ADO.Net EntityDataModel and the DomainService to work with my local database, so the error is probably somewhere there.

How would I debug this error? I have no previous experience with databases. I'm using SQL Server 2012 with a Northwind database adapted for 2012, while the tutorial was written with SQL Server 2008 RC.


Solution

  • Here is what I had to do to solve the problem. Josh's answer was part of the solution, but I also had to add [Include] attributes to the metadata:

    In MyDomainService.cs, add .Include():

    public IQueryable<Order_Detail> GetOrder_Details()
        {
            return this.ObjectContext.Order_Details.Include("Order").Include("Product");
        }
    

    In MyDomainService.metadata.cs, add [Include]:

    internal sealed class Order_DetailMetadata
        {
    
            // Metadata classes are not meant to be instantiated.
            private Order_DetailMetadata()
            {
            }
    
    
            [Include]
            public Order Order { get; set; }           
    
            [Include]
            public Product Product { get; set; }
    
    
        }
    }
    

    This is described in detail at this website, thanks to Brian Noyes for pointing it out to me.