0

我有一个涉及以下 3 个实体的 linq 查询:

public class LandPoint
{
    ...
    public OlsonTimeZone TimeZone { get; set; }
}

public class OlsonTimeZone : TimeZone
{
    ...
    public virtual ICollection<WindowsTimeZone> Windows { get; set; }
}

public class WindowsTimeZone : TimeZone
{
    ...
    public virtual ICollection<OlsonTimeZone> Olson { get; set; }
}

所以一个 LandPoint 有一个 OlsonTimeZone,它有零个或多个 WindowsTimeZone。

如果OlsonTimeZone 有任何WindowsTimeZones 或OlsonTimeZone 名称(以'Olson:' 为前缀)作为后备以及有关点本身的信息,我想要做的是获取WindowsTimeZone 名称(以'Windows:' 为前缀)。

我写的是:

 return db.LandPoints.Where(x => x.GeoNameID == ID).Take(1).Select(x => new LandPoint
        {
            TimeZone = x.TimeZone
                            .Windows.Select(t => "Windows:" + x.Name)
                            .Union(new[] { "Olson:" + x.TimeZone.Name })
                            .FirstOrDefault()
        }).First();

理论上哪个应该做我想要的。除了我测试它的给定点(我知道与 WindowsTimeZone 相关联)它返回 OlsonTimeZone 而不是 WindowsTimeZone。如果对于相同的 ID,我写以下内容:

return db.LandPoints.Where(x => x.GeoNameID == ID).Take(1).Select(x => new LandPoint
        {
            TimeZone = x.TimeZone
                            .Windows.Select(t => "Windows:" + x.Name)
                            .FirstOrDefault()
        }).First();

我得到了 WindowsTimeZone。

我确信我可以使用 CASE 语句重写它,但我觉得这更优雅。由于它的行为方式有点违反直觉并且理解它为什么这样做会帮助我更好地了解 linq 查询如何转换为 sql,我决定在这里发布一个问题。

那么它为什么要这么做呢?上面的代码是否有一些补充可以使它工作(维护 UNION 语句)?

提前感谢约翰

4

1 回答 1

0

这是因为 union 不保证排序。您不能在不订购的情况下根据物品的顺序提出任何特殊的期望。但是您的代码应该触发NotSupportedException,因为这是不允许的:db.LandPoints.Select(x => new LandPoint ...

如果您有LandPoint实体框架映射的实体,则无法在 Linq-to-entities 中投影到此类型。

于 2012-09-29T16:48:37.680 回答