【问题标题】:LINQ query continues to return null after 1st successful call第一次成功调用后,LINQ 查询继续返回 null
【发布时间】:2020-04-13 20:15:05
【问题描述】:

我的 ASP.NET MVC Web 应用程序中有一个上传功能,允许用户上传文档。然后系统使用各种OCR API从上传的文档中读取数据,然后将这些数据保存在数据库的“SecondarySchoolSurvey”表中。我在上传代码中有一个 LINQ 查询,它在数据库“SecondarySchoolSurvey”表中找到与传入的 Id 匹配的行。然后更新该行中的各个字段并将其保存回数据库中。

现在这个上传功能第一次运行良好。虽然如果我再次尝试使用上传功能(不重新启动 IIS 服务器)那么它会抛出以下错误Object reference not set to an instance of an object.

设置各种断点后,我注意到 LINQ 查询:var s1 = db.SecondarySchoolSurveys.FirstOrDefault(s => s.Id == id); 在第二次调用时返回 null,即它没有找到与传入的 Id 匹配的记录,即使它存在于数据库中。

所以现在,每次我想测试上传功能后,我都需要重置网络应用 IIS 服务器。否则,此 LINQ 查询将在我第二次尝试上传文档时返回 null。有没有人见过这样的事情?我不确定它提供代码会有多大用处,但这里是一类,它包含 LINQ 查询:

public class SurveyCheckboxAnswers
{
    private RDSContext db = new RDSContext();

    //Adds Question 2 answer
    public void AddQ2Answer(SurveyCheckboxCollections checkboxes, int id)
    {
        //find Survey record in db which matches id in order to update with checkbox data
        var s1 = db.SecondarySchoolSurveys.FirstOrDefault(s => s.Id == id);

        CheckboxData q2Male = checkboxes.SecondarySchoolCheckboxes["Q2Male"];
        CheckboxData q2Female = checkboxes.SecondarySchoolCheckboxes["Q2Female"];
        CheckboxData q2Other = checkboxes.SecondarySchoolCheckboxes["Q2Other"];
        CheckboxData q2DontWantToSay = checkboxes.SecondarySchoolCheckboxes["Q2DontWantToSay"];

        //numbers of checkboxes marked for validation
        int checkboxValidaiton = 0;

        //update SecondarySchoolSurvey checkbox answers in database with IsChecked values from checkbox dictionary 
        if (q2Male.IsChecked)
        {
            s1.Q2 = Gender.Male;
            checkboxValidaiton++;
        }
        if (q2Female.IsChecked)
        {
            s1.Q2 = Gender.Female;
            checkboxValidaiton++;
        }
        if (q2Other.IsChecked)
        {
            s1.Q2 = Gender.Other;
            checkboxValidaiton++;
        }
        if (q2DontWantToSay.IsChecked)
        {
            s1.Q2 = Gender.None;
            checkboxValidaiton++;
        }

        //validate only 1 checkbox has been marked 
        if(checkboxValidaiton == 0)
        {
            s1.Flag = true;
            s1.FlagContent += "| Question2: no checkboxes marked. ";
        }
        else if (checkboxValidaiton > 1)
        {
            s1.Flag = true;
            s1.FlagContent += "| Question2: more than 1 checkboxes marked. ";
        }

        db.SaveChanges();

    }

    //Adds Question 6 answer
    public void AddQ6Answer(SurveyCheckboxCollections checkboxes, int id)
    {
        //find Survey record in db which matches id in order to update with checkbox data
        var s1 = db.SecondarySchoolSurveys.FirstOrDefault(s => s.Id == id);

        CheckboxData q6Higher = checkboxes.SecondarySchoolCheckboxes["Q6Higher"];
        CheckboxData q6Ordinary = checkboxes.SecondarySchoolCheckboxes["Q6Ordinary"];
        CheckboxData q6Other = checkboxes.SecondarySchoolCheckboxes["Q6Other"];


        //numbers of checkboxes marked for validation
        int checkboxValidaiton = 0;     

        if (q6Higher.IsChecked)
        {
            s1.Q6a = MathLevel.Higher;
            checkboxValidaiton++;
        }
        if (q6Ordinary.IsChecked)
        {
            s1.Q6a = MathLevel.Ordinary;
            checkboxValidaiton++;
        }
        if (q6Other.IsChecked)
        {
            s1.Q6a = MathLevel.Other;
            checkboxValidaiton++;
        }

        //validate only 1 checkbox has been marked 
        if (checkboxValidaiton == 0)
        {
            s1.Flag = true;
            s1.FlagContent += "| Question6: no checkboxes marked. ";
        }
        else if (checkboxValidaiton > 1)
        {
            s1.Flag = true;
            s1.FlagContent += "| Question6: more than 1 checkboxes marked. ";
        }

        db.SaveChanges();
    }

    //Adds Question 7 answer
    public void AddQ7Answer(SurveyCheckboxCollections checkboxes, int id)
    {
        //find Survey record in db which matches id in order to update with checkbox data
        var s1 = db.SecondarySchoolSurveys.FirstOrDefault(s => s.Id == id);

        CheckboxData q7Physics = checkboxes.SecondarySchoolCheckboxes["Q7Physics"];
        CheckboxData q7Biology = checkboxes.SecondarySchoolCheckboxes["Q7Biology"];
        CheckboxData q7Chemistry = checkboxes.SecondarySchoolCheckboxes["Q7Chemistry"];
        CheckboxData q7Science = checkboxes.SecondarySchoolCheckboxes["Q7Science"];
        CheckboxData q7None = checkboxes.SecondarySchoolCheckboxes["Q7None"];

        //numbers of checkboxes marked for validation
        int checkboxValidaiton = 0;

        if (q7Physics.IsChecked)
        {
            s1.Q7 = "Physics";
            checkboxValidaiton++;
        }
        if (q7Biology.IsChecked)
        {
            s1.Q7 += "Biology";
            checkboxValidaiton++;
        }
        if (q7Chemistry.IsChecked)
        {
            s1.Q7 += "Chemistry";
            checkboxValidaiton++;
        }
        if (q7Science.IsChecked)
        {
            s1.Q7 += "Science Junior";
            checkboxValidaiton++;
        }
        if (q7None.IsChecked)
        {
            s1.Q7 += "None";
            checkboxValidaiton++;
        }

        //validate only 1 checkbox has been marked 
        if (checkboxValidaiton == 0)
        {
            s1.Flag = true;
            s1.FlagContent += "| Question7: no checkboxes marked. ";
        }

        db.SaveChanges();
    }
...
...
...
}

【问题讨论】:

  • 在每个函数中,尝试将代码包装在 using 语句中:using (var context = new RDSContext())

标签: c# asp.net asp.net-mvc linq


【解决方案1】:

您的问题很可能在于您正在为 db 上下文使用私有变量。使用上下文打开/关闭与数据库的连接的适当方法是使用 using 语句,如下所示:

using(var db = new RDSContext())
{
    //...Do work here with your context
}

MSDN

上下文的生命周期从创建实例时开始,到实例被释放或垃圾回收时结束。如果您希望将上下文控制的所有资源都放置在块的末尾,请使用 using。使用 using 时,编译器会自动创建一个 try/finally 块,并在 finally 块中调用 dispose。

【讨论】:

  • 那么我应该删除private RDSContext db = new RDSContext();,然后将每个方法包装在using(var db = new RDSContext()) 块中吗?
  • 是的,先生! @craig2020
  • @craig2020。是的。
  • 另一条建议是仅在需要时才将 using 语句保持打开状态。您的目标应该始终是尽快打开/关闭连接。 @craig2020
  • 完美的家伙,非常感谢!我试图简单地使用 db.Dispose() 这显然不是打开/关闭数据库连接的推荐方法。在使用块包装每个方法代码后,它现在可以正常工作了
【解决方案2】:

由于您的查询正在运行但返回 null,因此您的数据库上下文可能是有效的。这意味着问题很可能是查询本身。我怀疑在随后的运行中,您传入了一个不同的 id,它在您的数据库中没有记录。向数据库询问与提供的 id 匹配的第一条记录(如果有)返回 null。使用断点检查提供的id 和生成的sql。在您的数据库中检查您的 id 是否有一行。

另一方面,如果您希望查询始终返回一行,我建议您使用方法FirstSingle 而不是FisrtOrDefualt。如果没有匹配的行,这将引发错误,这保证如果没有引发错误,则返回非空结果。优点是在该方法之后您现在知道有匹配的行,否则您可能必须包含一个空检查。

这些运算符有一张很棒的表here

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-05-31
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多