【问题标题】:Entity Framework is not able to pull specific record by its ID in C# back end实体框架无法在 C# 后端通过其 ID 提取特定记录
【发布时间】:2020-01-09 17:30:42
【问题描述】:

假设我有一个名为 Books 的表,其中的记录很少,如下所示

ID    BookName
1      Book1
2      Book2
3      Book3

当我使用如下记录 ID 从我的 C# 后端查询上表时

var result = context.Books.where(b => b.ID == 1).FistOrDefault();

对于 ID = 1,我得到 null,但对于 ID 2,3,我得到整个记录。当我在 SSMS 上直接查询记录 ID = 1 时,我得到记录 ID 1。 这对我来说没有意义,为什么以及如何发生。任何帮助或线索将不胜感激。

【问题讨论】:

  • 您确定您的 BookName 表中有 ID == 1 的记录吗?
  • 你能分享一下实际的课程,并从 ID = 1 的 BookName 中选择 top(1) 并确保它返回吗?
  • 我刚刚编辑了这个问题,是的,我在@AustinTFrench Jawad 表中确实有记录 ID = 1
  • 如果你提取所有数据,它会检索 ID = 1 的记录吗?

标签: c# asp.net asp.net-mvc entity-framework


【解决方案1】:

您需要查询表书。请更改您的查询如下:

var result = context.Books.Where(b => b.ID == 1).FistOrDefault();

var result = context.Books.FistOrDefault(b => b.ID == 1);

另外,如果它使用 ID 值 2 和 3,那么我接下来要检查的是 C# 实际指向的数据库。我还将检查 Books 表存在的架构。默认情况下,EF 查询具有 dbo 模式的表,除非您另有定义。

接下来,我会检查正在发送到数据库的查询。为此,将context.Books.Where(b => b.ID == 1) 提取到变量中并获取sql 查询并在SSMS 中手动运行。

var queryableBooks = context.Books.Where(b => b.ID == 1); var result = queryableBooks.FirstOrDefault(); // 这里有个断点

然后在调试期间,通过 Quick Watch 验证 queryableBooks SQL。您将看到如下内容:

【讨论】:

  • @CodeGoorila 您是否正在连接手动查询的同一个数据库?您能否检查连接字符串指向的位置以及架构。默认情况下,除非您另有定义,否则查询具有 dbo 模式的表。
  • 是的,我确实检查了我的连接字符串,它与我手动查询的字符串相同......它超级奇怪
  • @CodeGoorila 接下来,我要做的是,将没有 FirstOrDefault 的 context.Books.Where(b => b.ID == 1) 提取到变量中,在该行设置一个断点并获取来自“快速观看”的 SQL 查询。请在此处发布该查询或自己验证该查询。或者,您可以通过属性 Database.Log 在上下文级别启用数据库日志记录。记录所有数据库查询。
  • @CodeGoorila 你有机会看到查询并弄清楚发生了什么吗?
【解决方案2】:

或者,对数据库运行跟踪以捕获实际运行的 SQL 语句,在代码中使用断点,启动跟踪并执行读取行。跟踪将显示正在运行的确切 SQL 语句。然后,您可以将这些语句复制到 SSMS 中以检查它们返回的内容。我用于 SQL Server 的一个简单的跟踪工具是 ExpressProfiler,它是在启用 SQL Server Express 跟踪的时代。虽然我建议从源代码 (https://github.com/ststeiger/ExpressProfiler) 构建它,而不是像 Sourceforge 这样的任何安装程序。 SSMS 在 Tools/SQL Server Profiler 下有探查器,默认情况下会捕获更多的噪音。这两种工具对于调查 EF 怪异和性能都是非常宝贵的。

如果context.Books.Where(b => b.ID == 1).SingleOrDefault() 返回#null,我会查看在您的数据库上为该语句捕获的SQL。将其与 b => b.ID == 2 进行比较。

如果您的跟踪没有为 1 或 2 捕获任何内容,但您看到了 ID = 2 场景的结果数据,则说明您的 DbContext 没有指向数据库/服务器您认为是这样,或者您的 DbContext 设置有问题。

如果您的跟踪确实捕获了 1 和 2 的某些内容,但您只看到了 #2 的数据,请检查 #1 的查询是否执行并返回数据。如果查询看起来有效但您的代码没有看到 ID #1 的任何内容,那么您的 DbContext 不知何故处于 ID #1 已被删除的状态。我将添加代码来检查 DbContext 的 ChangeTracker,以查明是否有 #1 的条目处于已移除的实体状态。您可能正在运行的代码意外地级联删除,但未调用 SaveChanges 或未成功。长时间运行的 DbContext 实例很容易出现此类问题。

测试以下内容:

而不是

var result = context.Books.where(b => b.ID == 1).FirstOrDefault(); 

使用这个:

using(var testContext = new MyDbContext())
{
    var result = testContext.Books.where(b => b.ID == 1).SingleOrDefault(); 
}

用您的应用程序 DbContext 替换 MyDbContext。这消除了任何具有长期运行 DbContext 状态的有趣业务。上下文仍然可以执行 SQL,但返回处于缓存状态的内容。

注意:查询数据时,如果您期望 0..1 个结果,请选择 SingleOrDefault 而不是 FirstOrDefault。像 First 这样的操作应该只在您期望 0..many 但只关心第一个结果时使用,并且它们应该始终与 Order By 条件一起使用以确保可预测的排序。

【讨论】:

    猜你喜欢
    • 2013-06-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-10-31
    • 2018-12-12
    • 1970-01-01
    相关资源
    最近更新 更多