ASP.Net MVC 3,复杂对象和延迟加载

时间:2011-08-21 14:39:49

标签: asp.net-mvc-3 entity-framework-4.1 lazy-loading

首先,我是ASP.Net MVC 3的新手,我也使用EF 4.1。

我有一个复杂的对象,类似于让我们说一个包含Category对象的Product对象。所以我们有Product.CategoryId,Product.Category和一些额外的属性。我还有一个表单来创建带有下拉列表的产品来选择类别。

在我的控制器中,在创建产品之后,我需要访问Category的某些属性来执行一些额外的操作。但是,虽然设置了Product.CategoryId,但我无法访问Product.Category.SomeProperty,因为Product.Category为null。我希望使用一些延迟加载自动加载Product.Category,但它似乎不是。

我的控制器中的代码如下所示:

[HttpPost]
public ActionResult Create(Product product)
{
   if (ModelState.IsValid)
    {
        db.Products.Add(product);
        db.SaveChanges();

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

现在,这不起作用,因为product.Category为null。我需要添加什么才能访问SomeProperty?

3 个答案:

答案 0 :(得分:7)

延迟加载在此方案中不起作用,因为您要添加新对象。延迟加载将适用于由EF上下文创建的“代理”实体。

所以你在这里可以做的是explicitly load导航属性。

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

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

    string someString = product.Category.SomeProperty;

答案 1 :(得分:1)

延迟加载在您的情况下不起作用,因为传入控制器操作的product不是代理对象,而是由模型绑定器创建为普通的Product实例。

如果product被创建为代理,您的期望是什么:

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

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

Category类的Product属性当然必须是virtual才能延迟加载。

在您的情况下它没有帮助,因为模型绑定器不会创建代理。

解决方案:要么明确加载(请参阅@ Eranga的答案),或者如果您真的只需要检查类别中的SomeProperty获取投影中的值:

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

...或(因为你有类别的关键字)......

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

答案 2 :(得分:0)

您可能需要在实体框架对象上下文中显式启用延迟加载,如MSDN文章How to: Use Lazy Loading to Load Related Objects中所述

  

在Entity Framework运行时中,默认值为   ObjectContext实例中的LazyLoadingEnabled属性为false。

db.ContextOptions.LazyLoadingEnabled = true;

Loading Related Objects文章中提供了更多详细信息,请参阅标记为“Lazily Loading Entity Objects”的部分。