重构代码后为什么得到“对象引用未设置为对象的实例”?

问题描述

| 我有一个包含几列的表,其中一列是“所有者”的FK ID。 在我的删除语句中,我有以下代码
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。 因此,问题在于我需要以下方面的帮助: 当数据库具有正确的ID时,我无法弄清为什么它为Null。 在运行ѭ5running之后的第一个示例中,我无法弄清楚为什么它得到正确的值。 最重要的是,我需要做什么来修复它?我猜我已经把某个大地方弄乱了,但我只是看不到它。     

解决方法

           我不知道为什么它为空   从数据库具有   正确的ID。 这条线...
EmailTemplate EmailTemplate = db.EmailTemplates.Find(id);
...将永远不会加载导航属性(在您的情况下为
CompanyID
)。导航属性仅预先加载(with12ѭ),显式加载或延迟加载。您似乎没有启用延迟加载,否则访问
CompanyID
应该会自动加载该属性。而且您没有利用其他两个选项。   我不知道为什么会这样   第一个示例中的正确值   运行SelectCompany()之后。 可能是因为关系跨度。当您使用“ 14”方法将公司加载到上下文中时,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();
或启用延迟加载。 (在您的特殊情况下,我宁愿急切加载。)     ,        
SelectCompany
必须执​​行一些填充
CompanyID
的代码。我的猜测是您使用的是延迟加载的ORM,并且SelectCompany导致填充CompanyID。