首先,我是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?
答案 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”的部分。