【发布时间】:2021-07-22 16:44:46
【问题描述】:
作为将我的 ASP.NET MVC 项目升级到 .NET Framework v4.8 和 ASP.NET MVC v5.2.7 的一部分,Entity Framework 也从 v5.0.0 升级到 v6.4.4;之后我注意到使用 Any() 构造的一个奇怪的变化。
顺便说一句,我也按照这里的步骤操作:https://docs.microsoft.com/en-us/ef/ef6/what-is-new/upgrading-to-ef6
我的项目中有这段代码(升级前后代码相同)
[HttpPost]
public ActionResult Create(Course course)
{
...
if (context.Courses.Any(c => c.ExternalCourseNumber == course.ExternalCourseNumber))
{
throw new Exception(Resources.Global.ExternalCourseIdAlreadyExists);
}
...
}
这是一种验证,是创建新Course 的一部分。 Course 对象是传递给 Create 方法的模型,而 ExternalCourseNumber 字段在 Web 表单上为空,因此当我在 Visual Studio 中调试时,course.ExternalCourseNumber 的值为 null。
关键是,如果提供了ExternalCourseNumber,则它不能存在于任何现有课程中,但是当它没有提供时,我不想抛出验证错误。
在升级之前,当ExternalCourseNumber 保留为空/null 时,此验证不会引发验证错误。升级后,我的代码抛出验证错误。
即在我看来:
Courses.Any(c => c.ExternalCourseNumber == course.ExternalCourseNumber)
在升级后与 null 比较时行为发生了变化....这让我感到困惑?!?
我知道如何通过测试空值来解决问题,但行为的变化让我担心,因为它也可能影响其他功能,所以我想了解发生了什么?
== 运算符是否也开始匹配 NULL 值或者我遗漏了什么?
=== 更新:从 EF6 生成的 SQL =====
我设法使用 EF6 日志框架来查看 SQL:
SELECT
CASE WHEN ( EXISTS (SELECT
1 AS [C1]
FROM [dbo].[Courses] AS [Extent1]
WHERE ([Extent1].[ExternalCourseNumber] = @p__linq__0) OR (([Extent1].[ExternalCourseNumber] IS NULL) AND (@p__linq__0 IS NULL))
)) THEN cast(1 as bit) ELSE cast(0 as bit) END AS [C1]
FROM ( SELECT 1 AS X ) AS [SingleRowTable1]
...这样就解释了为什么查询将包括 ExternalCourseNumber 为空的课程。但是为什么/什么时候改变了?为什么 EF5 的行为方式不同?这似乎是一个“重大变化”?
PS 我不知道如何查看在 EF5 中生成的 SQL...有什么建议吗?
【问题讨论】:
-
生成的sql是什么样的?
-
@DavidL,啊,对,好问题——我怎样才能“拦截”SQL?
-
在
OnConfiguring中,您可以添加options.LogTo(Console.WriteLine);(我猜这也适用于EF 6) -
我无法让 OnConfiguring 工作,但我设法通过 EF6 的日志记录框架 (blog.oneunicorn.com/2013/05/08/…) 查看了 SQL。 SQL 已在主要问题中列出。 ...但是,我不知道如何查看 EF5 中生成的 SQL?
标签: c# asp.net-mvc entity-framework-6