SQL 查询显示了良好的数据库值,但 LINQ to Entity 框架从无处获得空值

Posted

技术标签:

【中文标题】SQL 查询显示了良好的数据库值,但 LINQ to Entity 框架从无处获得空值【英文标题】:SQL query shows good database values, but LINQ to Entity framework brings a null value from nowhere 【发布时间】:2014-05-03 17:40:17 【问题描述】:

我在这里遇到了一个非常奇怪的问题,我不知道为什么。

我应该在 C# 中制作小型 localdb 控制台应用程序。目标是在数据库中输入人员(实际上是教师),并提供一定数量的信息。

我有几个课程,但其中 2 个在这里很重要:认证和符号。 证书是教授的证书。

这些类的代码是这样的:

class Certification

    public int CertificationID  get; set; 
    public virtual Teacher Teacher  get; set; 
    public virtual Course Course  get; set; 
    public string CertificationName  get; set; 
    public virtual Notation Notation  get; set;     
    
class Notation

    public int NotationID get;set;
    public string Note get;set;

没什么太危险的。通过迁移,我创建了我的数据库,它们看起来应该是这样的:

认证:

CertificationID (PK)
CertificationName
Course_CourseID (FK to another class, course)
Notation_NotationID (FK to notations)
Teacher_TeacherID (FK to the teachers)

符号:

NotationID (PK)
Note

我的程序允许我添加教师,并提供我需要的所有信息,例如他们的证书。在这里,我做了一些假老师,有假人证书。 如果我调用 SELECT * FROM Certification ,我得到的正是我应该得到的,像这样的一行:

CertificationID = 6
CertificationName = placeholder
Course_CourseID = 13
Notation_NotationID = 12
Teacher_TeacherID = 5

这一切都是正确的。 CourseID 链接到数据库中的实际课程,NotationID 链接到实际笔记中,Teacher 也链接到实际教师。一切都很好!

现在,我只想展示我们老师的证书:

var certifs = from c in db.Certifications where c.Teacher.TeacherID == item.TeacherID select c;

foreach(var v in certifs )

    var course = (from c in db.Courses where c.CourseID == v.Course.CourseID select c).First();
    var note = (from n in db.Notations where n.NotationID == v.Notation.NotationID select n.NotationID).First();

    Console.WriteLine("Name: " + v.CertificationName + ", related to the " + course.CourseName + " course, with a note of " + note);

    Console.WriteLine("");

而且它不起作用。当我的 foreach 循环开始时,我在循环中的第一项没有对符号的任何引用。其他一切都很好:课程和教师的外键都在这里,并且有效,但对于符号,我只得到一个空值。所以我的认证项看起来更像:

CertificationID = 6
CertificationName = placeholder
Course_CourseID = 13
Notation_NotationID = null
Teacher_TeacherID = 5

基本上,如果我执行 SQL 查询,我在数据库中的行非常好,但通过实体框架(和 LINQ)调用它会返回一个 null 值作为表示法。 (调用 var note 等时会抛出异常......

有人对此有任何想法吗?我真的被困在这上面了。

如果我的英语不够好,我很抱歉。如果你们需要更多信息,尽管问。

JC 回答:

延迟加载无法正常工作。急切加载解决了这个问题。

【问题讨论】:

我已经编辑了你的标题。请参阅“Should questions include “tags” in their titles?”,其中的共识是“不,他们不应该”。 【参考方案1】:

在你的队伍中

var note = (from n in db.Notations 
where n.NotationID == v.Notation.NotationID 
select n.NotationID).First();

您正在选择 n.NotationID only,它只会返回一个整数。尝试将select 更改为select n

【讨论】:

【参考方案2】:

问题是您在检索认证实体时没有填充导航属性。然后你尝试访问它们,它们是空的。

您需要确保开启延迟加载:

Configuration.LazyLoadingEnabled = true; //In your DbContext's constructor

在这种情况下,仅访问课程和通知引用应该会导致它们被填充到单独的数据库事务中......

...或者您需要在查询 DbSet 时使用预先加载:

var certifs = from c in db.Certifications.Include(c=>c.Course).Include(c=>c.Notation) where ...

这将导致同时加载 Course 和 Notation 证书在一个数据库事务中全部加载。

【讨论】:

只是一个问题:First() 不会导致数据加载吗? 您正在针对 Notations 和 Courses DbSet 调用 First(),但在这些查询中,您尝试访问在循环外检索到的认证实体的 Course 和 Notation 属性。当v.Coursev.Notation 为空时,尝试访问v.Course.CourseIdv.Notation.NotationId 时出现空异常。 问题是,v.Course 不为空!因为我在循环中检索它们:foreach 检索它们。由于我的类 (iirc) 中的虚拟属性,延迟加载已经启用。那是实际的问题,除了符号之外,一切都加载得很好。见:dropbox.com/s/86aa1w9zjvurjv5/certstate.png 已测试添加 Configuration.LazyLoadingEnabled = true;正如我所想,它已经开始了,没有改变任何东西。 再次查看您的问题...如果启用延迟加载,则在您访问 Notation 和 Course 引用时,应使用相关的 Notation 和 Course 实体加载它们。那么你为什么要明确地查询它们呢?您应该可以省略from c in db.Courses ...from n in db.Notations 行并直接访问v.Notationv.Course 的属性:v.Course.CourseName

以上是关于SQL 查询显示了良好的数据库值,但 LINQ to Entity 框架从无处获得空值的主要内容,如果未能解决你的问题,请参考以下文章

在 Linq to SQL 查询中设置非列属性值

PHP/SQL:从数据库接收到的“假”值具有良好的查询

linq-sql中根据时间倒序查询怎么写?

LINQ学习笔记

EF Core 嵌套 Linq 选择导致 N + 1 个 SQL 查询

将T-sql查询转换为linq