Reputation: 121
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
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
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
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
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