Почему после рефакторинга моего кода я получаю «Ссылка на объект не установлена ​​на экземпляр объекта»? - PullRequest
0 голосов
/ 30 мая 2011

У меня есть таблица с несколькими столбцами, один из которых является идентификатором FK "владельца".

В моем операторе удаления у меня есть следующий код:

public ActionResult DeleteEmailTemplate(int id = 0)
{
    EmailTemplate EmailTemplate = db.EmailTemplates.Find(id);

    Company _Company = SelectCompany();

    if (_Company.id != EmailTemplate.CompanyID.id)
        return Content("Security Error");

    return Content("Passed... Do Delete stuff");
 }

Это отлично работает, но мне нужно сделать это во многих местах, поэтому я попытался извлечь метод, и теперь у меня есть:

public ActionResult DeleteEmailTemplate(int id = 0)
{
    EmailTemplate EmailTemplate = db.EmailTemplates.Find(id);

    if (!SecurityCheck(EmailTemplate.CompanyID.id))
         return Content("Security Fail");

    return Content("Passed... Do Delete stuff");    
}

Я думаю, что код для SecurityCheck не имеет отношения кЯ устанавливал точки останова и знаю, что ошибка в том, что когда вызывается SecurityCheck, EmailTemplate.CompanyID равен Null, но ... я не могу понять, почему это Null.

В первомНапример, это Null, но в тот момент, когда я выполняю SelectCompany() и проверяю EmailTemplate, EmailTemplate.CompanyID устанавливается на правильное значение, несмотря на то, что этот метод только заполняет объект _Company и больше ничего не трогает.

Во втором примере это снова Null, но остается нулевым.

Итак, проблемы в том, что мне нужна помощь:

Я не могу понять, почему это Null дляначать с того, что база данных имеет правильный идентификатор.

Я не могу понять, почему он получает правильное значение в файлеПервый пример после запуска SelectCompany().

И самое главное, что мне нужно сделать, чтобы это исправить? Я предполагаю, что перепутал где-то большое, но я просто не вижу его.

Ответы [ 2 ]

1 голос
/ 30 мая 2011

Я не могу понять, почему начать с того, когда база данных имеет правильный идентификатор.

Эта строка ...

EmailTemplate EmailTemplate = db.EmailTemplates.Find(id);

... никогда не будет загружать свойство навигации (CompanyID в вашем случае). Свойства навигации загружаются только с Include, явно загружаются или загружаются лениво. Похоже, у вас не включена отложенная загрузка, в противном случае доступ к CompanyID должен автоматически загрузить свойство. И вы не используете другие два варианта.

Я не могу понять, почему это становится правильное значение в первом примере после запуска SelectCompany ().

Вероятно, из-за продолжительности отношений. Когда вы загружаете компанию в контекст в своем методе SelectCompany, Entity Framework автоматически исправляет ссылки на другие объекты, которые уже загружены. По этой причине EmailTemplate.CompanyID заполняется автоматически.

И самое главное, что мне нужно сделать, чтобы это исправить?

Используйте один из трех вариантов, упомянутых выше:

Стремительная загрузка (одна поездка туда и обратно):

EmailTemplate EmailTemplate = db.EmailTemplates.Include(e => e.CompanyID)
    .Where(e => e.ID == id).SingleOrDefault();

явная загрузка (две поездки туда и обратно):

EmailTemplate EmailTemplate = db.EmailTemplates.Find(id);
db.Entry(EmailTemplate).Reference(e => e.CompanyID).Load();

Или включить отложенную загрузку.

(В вашем особом случае я бы предпочел энергичную загрузку.)

0 голосов
/ 30 мая 2011

SelectCompany должен использовать некоторый код, который заполняет CompanyID. Я предполагаю, что вы используете ORM с отложенной загрузкой, а SelectCompany вызывает заполнение CompanyID.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...