ASP.Net MVC 3, сложные объекты и отложенная загрузка - PullRequest
2 голосов
/ 21 августа 2011

Прежде всего, я новичок в ASP.Net MVC 3, и я также использую EF 4.1.

У меня есть сложный объект, похожий, скажем, на объект Product, содержащий объект Category. Итак, у нас есть Product.CategoryId, Product.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 ]

7 голосов
/ 21 августа 2011

Ленивая загрузка не будет работать в этом сценарии, потому что вы добавляете новый объект.Ленивая загрузка будет работать с объектами «Прокси», созданными в контексте EF.

Здесь вы можете явно загрузить свойство навигации.

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

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

    string someString = product.Category.SomeProperty;
1 голос
/ 21 августа 2011

Ленивая загрузка не работает в вашем случае, потому что 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();
0 голосов
/ 21 августа 2011

Вам может понадобиться явно включить отложенную загрузку в контексте объекта вашей структуры сущности, как описано в статье MSDN Как: использовать отложенную загрузку для загрузки связанных объектов

Вво время выполнения Entity Framework значение по умолчанию свойства LazyLoadingEnabled в экземпляре ObjectContext равно false.

db.ContextOptions.LazyLoadingEnabled = true;

Более подробная информация представлена ​​в статье Загрузка связанных объектов , простопосмотрите в разделе «Лениво загружаемые объекты».

...