开发者

ASP.Net MVC 3, Complex Objects and Lazy Loading

First of all, I am new to ASP.Net MVC 3, and I am also using EF 4.1.

I have a complex object, something similar to let's say a Product object containing a Category object. So we have Product.CategoryId, Product.Category and some extra properties. I also have a form to create products with a dropdown list to select the category.

In my controller, after the product has been created, I need to have access to some property of the Category to perform some extra stuff. However, although Product.CategoryId is set, I cannot access Product.Category.SomeProperty because Product.Category is null. I expected Product.Category would be loaded automatically using some lazy loading, but it does not seem to be.

The code in my Controller looks like this:

[HttpPost]
public ActionResult Create(Product product)
{
   if (ModelState.IsValid)
    {
        db.Products.Add(开发者_如何转开发product);
        db.SaveChanges();

        string someString = product.Category.SomeProperty;
        ...

Now, this does not work because product.Category is null. What do I need to add so that I can access SomeProperty?


Lazy loading will not work in this scenario because you are adding a new object. Lazy loading will work on "Proxy" entities created by EF context.

So what you can do here is explicitly load the navigational property.

    db.Products.Add(product);
    db.SaveChanges();

    db.Entry(product).Reference(p => p.Category).Load();

    string someString = product.Category.SomeProperty;


Lazy loading doesn't work in your case because the product which is passed in into the controller action is not a proxy object but created as an ordinary Product instance by the model binder.

What you expect would work if product is created as a proxy:

var product = db.Products.Create();
product.CategoryId = 1;
db.Products.Add(product);
db.SaveChanges();

string someString = product.Category.SomeProperty;
// Category gets lazily loaded now

The Category property on the Product class must be virtual of course to have lazy loading working at all.

It doesn't help you in your situation because the model binder doesn't create a proxy.

Solutions: Either explicite loading (see @Eranga's answer) or in case you really only need to inspect the SomeProperty of the category fetch the value in a projection:

string someString = db.Entry(product).Reference(p => p.Category).Query()
    .Select(c => c.SomeProperty).SingleOrDefault();

...or (because you have the key of the category)...

string someString = db.Categories.Where(c => c.Id == product.CategoryId)
    .Select(c => c.SomeProperty).SingleOrDefault();


You may need to explicitly enable lazy loading in your entity framework object context, as described in the MSDN article How to: Use Lazy Loading to Load Related Objects

In the Entity Framework runtime, the default value of the LazyLoadingEnabled property in an instance of ObjectContext is false.

db.ContextOptions.LazyLoadingEnabled = true;

More detail is provided in the Loading Related Objects article, just look in the section labeled "Lazily Loading Entity Objects".

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜