0

我有一个数据库,两个表之间有 1..many 关系,称它们为 Color 和 Car。颜色与 1..many 与 Cars 相关联。就我而言,可以随时删除颜色至关重要。没有级联删除,所以如果一个颜色被删除,汽车的 Color_ID 字段指向不存在的东西。还行吧。它们通过名为 Color_ID 的 FK 关联。

当我这样做时,问题就来了:

var query = context.Cars.Include(x => x.Colors);

这仅返回具有关联 Color 记录的 Cars。我真正想要的是所有汽车,即使它们的颜色不存在,所以我可以使用 GridView 进行模型绑定,即 <asp:Label runat="server" Text='<%# Item.Colors == null ? "Color Deleted!" : Item.Colors %>' />

如果我删除 .Include() 并诉诸延迟加载,所有这些都可以正常工作。然后 Item.Car.Color 为空。完美的。但是,我非常担心对大量结果集进行过多的数据库查询,这当然是可能的。

避免过多 db 查询的一种解决方案是从数据源查询中返回一个匿名类型,其中包含网格所需的所有特定相关信息位,并将我的所有“Item”样式绑定转换为良好的 'ol Eval()。但后来我失去了强类型,以及 Value Provider 属性带来的简单性。我不想重写所有这些。

我是对的,我必须选择其中一个吗?即使没有颜色记录,如何调整查询以返回所有汽车记录?如果我尝试使用 .Include() 进行急切加载,我想我会搞砸的。我需要一个 .IncludeWithNulls() 之类的东西。

更新:刚想到这个。就查询成本而言,我不知道这有多难看,但它确实有效。有没有更好的办法??

var query = context.Cars.Include(x => x.Colors);
var query2 = context.Cars.Where(x => !context.Colors.Any(y => y.Color_ID == x.Color_ID);
return query.Union(query2);
4

1 回答 1

0

问题是不正确的末端多重性。我真正需要的不是 1..many,而是 0..many。这样,Entity Framework 会从 .Include() 生成左外连接而不是内连接。这是有道理的,在上面的示例中,实际颜色记录可能为零。让我感到困惑的是,在 SQL 数据库中,我从未将这些外键字段设置为可为空,因为在创建时,它们总是需要有效的外键。所以我将它们设置为可空并修复了我的 .edmx 表,一切正常。我确实不得不在这里和那里添加更多的空检查,例如我上面的问题中的那个,这在以前并不是绝对必要的,因为 .Include 现在正在提取引用缺失相关实体的记录,但没什么大不了的。

因此,我在数据库级别的非空检查上失败了,但我在 LINQ 查询中获得了一些一致的逻辑,这些逻辑与这些表的实际关联方式以及我期望得到的结果有关。

于 2013-04-10T01:03:08.767 回答