C# 选择整个表时返回空参数的Linq查询

C# 选择整个表时返回空参数的Linq查询,c#,asp.net-mvc,linq,entity-framework,C#,Asp.net Mvc,Linq,Entity Framework,我对Linq很陌生,但最近我一直在使用它,并且信心不断增强。我使用EF通过MVC项目中的上下文访问数据库 在这个实例中,我要做的就是从我的一个表中获取所有数据 var msgs = context.Messages.ToList(); 我觉得这很好,但是当我以后使用列表时: foreach(Message m in msgs) { var info = context.Contacts.Where(x => x.Id == m.recipient.Id)

我对Linq很陌生,但最近我一直在使用它,并且信心不断增强。我使用EF通过MVC项目中的上下文访问数据库

在这个实例中,我要做的就是从我的一个表中获取所有数据

var msgs = context.Messages.ToList();
我觉得这很好,但是当我以后使用列表时:

foreach(Message m in msgs)
{

     var info = context.Contacts.Where(x => x.Id == m.recipient.Id)
                                .Select(x => x.MobileNumber).FirstOrDefault();

}
消息对象有一个必需的
收件人
,它是一个联系人对象(我数据库中的另一个实体)

我在上面一行得到一个
NullArgumentException
,因为消息对象的收件人参数在我的列表中为null,尽管它们在数据库中不是null

奇怪的是,列表大小正确,因此它进入了foreach循环。正在正确选择列表,但根据我的调试器,所有属性都为空

对此我感到困惑,于是我跑了这条线:

console.WriteLine(context.Messages.Select(x => x.Recipient.FirstName).FirstOrDefault());
第一封邮件的收件人的名字被写入控制台。因此,当我单独选择时,我可以检索消息的收件人及其所有信息,但当尝试检索整个表并将其存储在列表中时,收件人对象为空

正如我所说,我是从包含上下文的MVC项目之外访问它的。我从另一个项目中使用它。但是,另一个项目包含对我的MVC项目(包含db的消息模型)和另一个项目(包含称为Message的不同类)的引用。这种模棱两可可能是问题的根源,还是我所做的有其他问题

编辑我显然对我的问题产生了一些困惑。问题是,一旦检索到列表,列表的大小就正确了,但是列表中消息对象的参数为空。例如,如果我写:

foreach (Message m in msgs)
        {

            Console.WriteLine("List Element Exists");
            if (m.Recipient != null)
            {
                Console.WriteLine(m.Recipient.FirstName);
            }
        }
我得到输出:


列表元素存在
列表元素存在
列表元素存在
列表元素存在

对于列表中的每个元素


JK

很可能是linq查询中
条件为null的结果

var info = context.Contacts.Where(x => x.Id == m.recipient.Id)
                                .Select(x => x.MobileNumber).FirstOrDefault()
此外,查询本身也存在一些问题,您可以编写与以下相同的查询:

var mobileNumber = string.Empty; //if it is not a string then initialize with proper value
var info = context.Contacts.FirstOrDefault(x => x.Id == m.recipient.Id);
if(info != null)
    mobileNumber = info.MobileNumber;
还有一个问题,;如果执行此行:

var msgs = context.Messages.ToList();
它将从数据库中获取所有
消息
;但是你只需要一个电话号码。因此,与其获取所有记录,不如执行我提供的查询,而不要调用foreach

编辑

执行
ToList()
时,立即执行db查询;这意味着将不会加载
邮件
对象的
收件人
属性。根据您使用的是延迟加载还是快速加载,您需要另一种机制来获取
Recipient
属性。有点像

var msgs = context.Messages.Include(b => b.Recipients).ToList();

如果您希望msg.Recipient包含某些内容(即在DB上编译数据),则这是一个映射问题。最常见的问题是收件人属性未标记为虚拟

编辑

或者,甚至最糟糕的是,该类被标记为密封的,但这通常不会发生在控制台上。WriteLine(String)不会在null参数上引发异常。告诉引发异常的确切位置。调试此异常时,
null
到底是什么?对于数据库中该字段为
null
的任何记录,我预计
m.Text
将为
null
。如果m为null,则可能是映射问题。此外,文本是否为字符串类型并直接映射到表?文本是否为数据库中的必填字段?我很抱歉,我简化了问题,试图显示孤立的问题。请看编辑。空异常指的是我的邮件的收件人对象。我的邮件有一个必需的收件人,这是一个联系人(我数据库中的另一个实体)。谢谢回复。这仍然抛出异常。异常是因为由于某种原因,
收件人
联系人对象在我的邮件列表中为空。我检索所有消息的原因是因为我在Foreach循环中以其他方式使用列表。您看到的这一行是大型流程的第一行。我需要所有的消息…我以前从未遇到过包含函数…但谢谢它工作得很好。所以我想,对于复杂的属性,你必须指定包含它们。我不知道延迟加载和渴望加载,因为我对这个领域很陌生。我只能接受一个答案,但我投了赞成票,因为我从这两个方面都学到了一些东西。谢谢您认为使用“急切加载”只加载给定情况下所需内容的优势更可取吗?