Entity framework 即使在得到 false 后评估子句
Entity framework evaluating clause even after getting false
var exercises = _repository.Exercises.Where(a =>
userPrincipal.User != null && // false
(
userPrincipal.Activated && a.PrivacyString == Privacy.PUBLIC_TO_REGISTERED_USERS.ToString() ||
userPrincipal.User.Id == a.User.Id && a.PrivacyString == Privacy.PRIVATE.ToString()
)
).ToList();
这是我的代码,这永远不会超出 false,但它也是 运行 底部子句。
基本上有空检查,但现在 EF 给我空指针错误
{"Non-static method requires a target."}
当我从查询中删除 userPrincipal.User.Id
时,我没有得到异常,所以我知道 userPrincipal.User
为空。
编辑:
_存储库定义。
public DbSet<Exercise> Exercises { get; set; }
IQueryable<Exercise> IRepository.Exercises {
get { return Exercises; }
}
编辑:EF 生成的查询。
SELECT
1 AS [C1],
CAST(NULL AS int) AS [C2],
CAST(NULL AS varchar(1)) AS [C3],
CAST(NULL AS varchar(1)) AS [C4],
CAST(NULL AS varchar(1)) AS [C5],
CAST(NULL AS varchar(1)) AS [C6],
CAST(NULL AS varchar(1)) AS [C7],
CAST(NULL AS int) AS [C8]
FROM ( SELECT 1 AS X ) AS [SingleRowTable1]
WHERE 1 = 0
空指针错误是检索 userPrincipal 变量 属性 值的结果,该变量是空引用。
EF 将查询转换为 SQL,并将所有使用的内存值转换为 sql 参数。例如,当您在查询中使用 userPrincipal.Activated 时,EF 会从表达式树中检索 PropertyInfo(或 FieldInfo 或 MethodInfo),并使用它从对象中检索值。为此,您需要引用包含该值的对象。如果该对象是空引用,则会出现您看到的异常。
简而言之:抛出异常是因为如果您使用的对象是空引用,EF 无法检索属性的值。
另请参阅:
有效的最终解决方案,在查询外部进行空检查:
var exercises = _repository.Exercises;
if (userPrincipal.User == null) {
exercises = exercises.Where(a => a.PrivacyString == Privacy.PUBLIC.ToString());
} else {
exercises = exercises.Where(a =>
a.PrivacyString == Privacy.PUBLIC.ToString() ||
userPrincipal.Activated && a.PrivacyString == Privacy.PUBLIC_TO_REGISTERED_USERS.ToString() ||
userPrincipal.User.Id == a.User.Id && a.PrivacyString == Privacy.PRIVATE.ToString());
}
var exercises = _repository.Exercises.Where(a =>
userPrincipal.User != null && // false
(
userPrincipal.Activated && a.PrivacyString == Privacy.PUBLIC_TO_REGISTERED_USERS.ToString() ||
userPrincipal.User.Id == a.User.Id && a.PrivacyString == Privacy.PRIVATE.ToString()
)
).ToList();
这是我的代码,这永远不会超出 false,但它也是 运行 底部子句。 基本上有空检查,但现在 EF 给我空指针错误
{"Non-static method requires a target."}
当我从查询中删除 userPrincipal.User.Id
时,我没有得到异常,所以我知道 userPrincipal.User
为空。
编辑:
_存储库定义。
public DbSet<Exercise> Exercises { get; set; }
IQueryable<Exercise> IRepository.Exercises {
get { return Exercises; }
}
编辑:EF 生成的查询。
SELECT
1 AS [C1],
CAST(NULL AS int) AS [C2],
CAST(NULL AS varchar(1)) AS [C3],
CAST(NULL AS varchar(1)) AS [C4],
CAST(NULL AS varchar(1)) AS [C5],
CAST(NULL AS varchar(1)) AS [C6],
CAST(NULL AS varchar(1)) AS [C7],
CAST(NULL AS int) AS [C8]
FROM ( SELECT 1 AS X ) AS [SingleRowTable1]
WHERE 1 = 0
空指针错误是检索 userPrincipal 变量 属性 值的结果,该变量是空引用。
EF 将查询转换为 SQL,并将所有使用的内存值转换为 sql 参数。例如,当您在查询中使用 userPrincipal.Activated 时,EF 会从表达式树中检索 PropertyInfo(或 FieldInfo 或 MethodInfo),并使用它从对象中检索值。为此,您需要引用包含该值的对象。如果该对象是空引用,则会出现您看到的异常。
简而言之:抛出异常是因为如果您使用的对象是空引用,EF 无法检索属性的值。
另请参阅:
有效的最终解决方案,在查询外部进行空检查:
var exercises = _repository.Exercises;
if (userPrincipal.User == null) {
exercises = exercises.Where(a => a.PrivacyString == Privacy.PUBLIC.ToString());
} else {
exercises = exercises.Where(a =>
a.PrivacyString == Privacy.PUBLIC.ToString() ||
userPrincipal.Activated && a.PrivacyString == Privacy.PUBLIC_TO_REGISTERED_USERS.ToString() ||
userPrincipal.User.Id == a.User.Id && a.PrivacyString == Privacy.PRIVATE.ToString());
}