我正在尝试使用以下查询返回布尔值:
var q = from inmate in context.Inmates
select new
{
inmate.Id,
IsCrazy = inmate.Certified != null
};
仅当可选的IsCrazy
导航属性不为null时, true
才应为Certified
。但是,无论IsCrazy
之间是否存在链接,Inmate > Certified
始终都会返回true。
使用上面的代码和以下数据:
Inmate { 1 } --> { Certified }
Inmate { 2 } --> NULL
Inmate { 3 } --> { Certified }
我期待以下结果:
1, true
2, false
3, true
然而,所有结果都是真实的。我做错了什么?
然后我试图改回可选的导航属性,但这似乎是做一个内连接而只有返回疯狂的囚犯:
Inmate { 1 } --> { Certified }
Inmate { 3 } --> { Certified }
// Inmate 2 is missing
编辑:忘记提及,我使用的是EF 4.0 Code First。
编辑2:
这是SQL输出
SELECT
[Extent1].[Id] AS [Id],
CASE WHEN (cast(1 as bit) <> cast(0 as bit))
THEN cast(1 as bit) WHEN (1 = 0) THEN cast(0 as bit) END AS [C1]
FROM [dbo].[Inmate] AS [Extent1]
对我来说完全错了;没有提到任何Certified
。
编辑3:
我在LINQPad中尝试了以下代码(删除了囚犯的事,这是我的实际代码):
from i in Ingredients
join m in Meats
on new { i.IngId, i.VersionId } equals new { m.IngId, m.VersionId } into temp
from t in temp.DefaultIfEmpty()
select new
{
IngId = i.IngId,
IsMeat = t.MeatTypeId == null ? false : true
};
这将返回具有正确true / false值的所有3000个结果。实体框架中的相同代码将仅返回已实现一对一关系的结果。
这是LINQPad生成的SQL:
-- Region Parameters
DECLARE @p0 Int SET @p0 = 0
DECLARE @p1 Int SET @p1 = 1
-- EndRegion
SELECT [t0].[IngId],
(CASE
WHEN ([t1].[MeatTypeId]) IS NULL THEN @p0
ELSE @p1
END) AS [IsMeat]
FROM [Ingredient] AS [t0]
LEFT OUTER JOIN [MeatIngredient] AS [t1] ON ([t0].[IngId] = [t1].[IngId])
AND ([t0].[VersionId] = [t1].[VersionId])
这是由EF生成的SQL:
SELECT
[Extent1].[IngId] AS [IngId],
cast(1 as bit) AS [C1]
FROM [dbo].[Ingredient] AS [Extent1]
INNER JOIN [dbo].[MeatIngredient] AS [Extent2]
ON ([Extent1].[VersionId] = [Extent2].[VersionId])
AND ([Extent1].[IngId] = [Extent2].[IngId])
答案 0 :(得分:1)
好吧,我已经设法通过向后思考让它按预期工作。即检查可以为空的肉有一个成分(或仍然与最初的例子,检查证书是否有一个有效的囚犯):
var q = from i in context.Ingredients
let m = i.Meat // AKA Certificate
select new
{
IngId = i.IngId,
IsMeat = m.Ingredient != null
};
对于这样一个简单的查询,SQL很讨厌。如果我自己编写存储过程,它的大小约为4倍。但是,它运行时间为57毫秒,因此不必担心。
答案 1 :(得分:0)
不知道这是否有帮助。但试试
IsCrazy =!inmate.Certified.Equals(System.DBNull.Value)
答案 2 :(得分:0)
继续尝试做左外连接:
var q = from inmate in context.Inmates
join c in Certified on inmate.cId equals c.Id into temp //replace with whatever you will join on
from temp in temp.DefaultIfEmpty()
select new { inmate.Id, IsCrazy = c.IsCertified != null }; //replace to what it is you want to check
会是这样的。有关更具体的示例,可能有助于在此处了解有关数据库结构的更多信息。希望这会有所帮助。