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

发布于 2024-11-10 15:47:47 字数 1295 浏览 0 评论 0原文

我有一个表,其中有几列,其中一列是“所有者”的 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 时,我无法弄清楚为什么它一开始就为 Null。

我不明白为什么在运行 SelectCompany() 后它在第一个示例中获得了正确的值。

最重要的是,我需要做什么来修复它?我猜我在某个地方搞砸了,但我只是没有看到它。

I have a table which has a few columns, one of which is an FK ID of the "owner".

In my delete statement, I have the following code:

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");
 }

That works fine, but, I need to do this in many places, so I tried to extract the method and I now have:

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");    
}

I think the code for SecurityCheck is not relevant as I have been setting breakpoints and I know that the error is because when SecurityCheck is called, EmailTemplate.CompanyID is Null, but... I can't work out why it is Null.

In the first example, it is Null, but the moment I do SelectCompany() and check EmailTemplate, EmailTemplate.CompanyID is set to the correct value, despite this method only populates the _Company object and does not touch anything else.

In the second example, it is Null again but stays null.

So, the problems are that I need help with:

I can't figure out why it is Null to begin with when the database has the correct ID.

I can't figure out why it is getting the correct value in the first example after running SelectCompany().

And most importantly, what do I need to do to fix it?, I am guessing I have messed up somewhere big, but I just don't see it.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

甲如呢乙后呢 2024-11-17 15:47:47

我不明白为什么它是空的
当数据库有以下内容时开始
正确的 ID。

这一行......

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

永远不会加载导航属性(在您的情况下是CompanyID)。导航属性只能预先加载(使用 Include)、显式加载或延迟加载。您似乎没有启用延迟加载,否则访问 CompanyID 应该自动加载该属性。而且您不会使用其他两个选项。

我不明白为什么会这样
第一个示例中的正确值
运行 SelectCompany() 后。

可能是因为关系跨度。当您在 SelectCompany 方法中将公司加载到上下文中时,实体框架会自动修复已加载的其他对象中的引用。因此,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();

或启用延迟加载。

(在你的特殊情况下,我更喜欢急切加载。)

I can't figure out why it is Null to
begin with when the database has the
correct ID.

This line ...

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

... would never load a navigation property (CompanyID in your case). Navigation properties are only eager loaded (with Include), explicitely loaded or lazily loaded. You don't seem to have lazy loading enabled, otherwise accessing CompanyID should load the property automatically. And you don't make use of the other two options.

I can't figure out why it is getting
the correct value in the first example
after running SelectCompany().

Probably because of relationship span. When you load the company into the context in your SelectCompany method, Entity Framework fixes automatically references in other objects which are already loaded. For this reason EmailTemplate.CompanyID gets populated automatically.

And most importantly, what do I need
to do to fix it?,

Use one of the three options mentioned above:

Eager loading (one round trip):

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

Explicit loading (two round trips):

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

Or enable lazy loading.

(In your special case I'd prefer eager loading.)

女皇必胜 2024-11-17 15:47:47

SelectCompany 必须执行一些填充 CompanyID 的代码。我的猜测是您正在使用带有延迟加载的 ORM,并且 SelectCompany 会导致 CompanyID 被填充。

SelectCompany must be exercising some code that populates CompanyID. My guess is you are using an ORM with lazy loading and SelectCompany causes the CompanyID to get populated.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文