我有一个表,它有几列,其中一列是"所有者"的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,但当我执行SelectCompany()
并检查EmailTemplate
时,EmailTemplate.CompanyID
被设置为正确的值,尽管此方法只填充_Company
对象,不涉及任何其他内容。
在第二个示例中,它再次为Null,但保持为Null。
所以,问题是我需要帮助:
当数据库有正确的ID时,我不明白为什么一开始它是空的。
我不明白为什么在运行SelectCompany()
之后,它在第一个示例中得到了正确的值。
最重要的是,我需要做些什么来修复它?,我猜我在某个大地方搞砸了,但我就是看不出来。
我不明白为什么对从数据库具有正确的ID。
这行。。。
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();
或者启用延迟加载。
(在您的特殊情况下,我更喜欢快速加载。)
SelectCompany
必须执行一些填充CompanyID
的代码。我的猜测是,您使用的是带有延迟加载的ORM,SelectCompany会导致CompanyID被填充。