EF 5联盟没有按预期工作

时间:2012-09-29 14:12:04

标签: c# linq-to-entities entity-framework-5

我有一个涉及以下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,它有零个或多个WindowsTimeZones。

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

我写的是:

 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语句)?

提前致谢 约翰

1 个答案:

答案 0 :(得分:0)

这是因为工会不保证订购。如果没有订购商品,您不能根据商品的顺序提出任何特殊期望。但是,您的代码应该触发NotSupportedException,因为这是不允许的:db.LandPoints.Select(x => new LandPoint ...

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