bluetxxth
bluetxxth

Reputation: 121

Create a LINQ query that fetches data from two Entities

I want to get to the product categories in a MVC project and use them to create a menu. The model resides on a WCF project so I have instantiated it as follows:

ServiceReference1.WSClient client = new ServiceReference1.WSClient();

My Product model is like this:

public class Product
{
    public int ProductID { get; set; }

    public string ProductName { get; set; }

    public string ProductImagePath { get; set; }

    public string Specifications { get; set; }

    public string Options { get; set; }

    public double? UnitPrice { get; set; }

    public int? CategoryId { get; set; }

    public  Category Category { get; set; }

    public int Stock { get; set; }
}

My Category model is like this:

public class Category
{
    public int CategoryID { get; set; }

    public string CategoryName { get; set; }

    public string Despcription { get; set; }

    public virtual ICollection<Product> Products { get; set; }

}

I want to get the product categories like this:

public PartialViewResult Menu()
{

    List<Product> products = client.GetAvailableProducts().ToList();


    IEnumerable<string> categories = products
                                 .Select(myproduct => myproduct.Category.CategoryName) // <- offending line
                                 .Distinct()
                                 .OrderBy(x => x);

    return PartialView(categories);
}

The method GetAvailableProducts() works because I get a list of products so I know that the service is working. However, when run the application, I get a null reference exception at the Linq query(see offending line above).

It seems to me that categories has to be instantiated but then, how to construct the LINQ query so that the Category is also instantiated? Can anyone point out how to do it?

BR,

Gabriel

Upvotes: 1

Views: 159

Answers (4)

Sani Huttunen
Sani Huttunen

Reputation: 24385

When you serialize the Products in the service you should use LoadWith to also serialize any linked entities. This is because the default is lazy loading and EF won't load the linked entities until accessed. When you serialize the Products, Category is not accessed. LoadWith will perform an eager load so that all data will be serialized.

Example:

public IEnumerable<Product> GetAvailableProducts()
{
  var ctx = new ProductsContext();

  DataLoadOptions dlo = new DataLoadOptions();
  dlo.LoadWith<Product>(p => p.Category);
  ctx.LoadOptions = dlo;

  return ctx.Products.ToList();
}

Edit:

Guess it's too late in the afternoon. :(

LoadWith is used in conjuction with Linq to SQL.
With Entity Framework you should use Include instead:

public IEnumerable<Product> GetAvailableProducts()
{
  var ctx = new ProductsContext();
  return ctx.Products.Include("Category").ToList();
}

Disclaimer: Code not tested

Upvotes: 3

Eric Scherrer
Eric Scherrer

Reputation: 3388

On your offending line, myproduct.Category, there is one or more null Category. You need to change

client.GetAvailableProducts().ToList();

to also pull down the Category that each product is composed of.

You should also guard for the inevitable null Category.

Upvotes: 1

Tim
Tim

Reputation: 15237

You're pulling down the Products successfully but your service is not pulling down the related categories.

Thus, when you do myproduct.Category.CategoryName, Category is always null.

You need to tell the service to return the related categories.

Upvotes: 2

RyanB
RyanB

Reputation: 757

It looks like your relationship is a 0 or 1 to many since CategoryId is an int?. If the Category is null, then you can't do Category.CategoryName. That's a null reference.

Upvotes: 1

Related Questions